I am designing a Q & A website use php. Here is the directory structure:
+include
db.php
user.php
template.php
...
question.php
+public
+images
+styles
.htaccess
index.php
...
I want to use index.php 's REQUEST_STRING to load a template.
For example: index.php?page=signin will load the function get_signin_template() in template.php. And will show the visitor a URL like http://example.com/signin/.
Here are my questions:
How to load different templates in index.php (what should do in this file)?
How to rewrite the url (using apache mod_rewrite)?
Answer to Question 1
$valid_templates = array('signin', 'logout', 'home');
if(isset($_GET['page'])
and in_array($_GET['page'], $valid_templates)) {
$function_name = 'get_' . $_GET['page'] . '_template';
$template = call_user_func($function_name);
}
See call_user_func() in the PHP manual and the in_array() function in the PHP manual.
I think it is also worth mentioning that I would not do it this way myself. Mapping URLs directly to functions is an inflexible way of doing things.
The reason I have added the $valid_templates array is to ensure the user doesn't attempt to change the URL in an attempt to call a nonexistant function etc. You would need to add each page/template function to it.
If you really like this way of working then I would recommend you check out Limonade as it uses a similar dispatch method as the one you are attempting to setup (the following example is from their official site):
require_once 'vendors/limonade.php';
dispatch('/', 'hello');
function hello()
{
return 'Hello world!';
}
run();
But is a little safer and easier to manage in my opinion. Plus all the "hard" plumbing work has been done and you can just focus on adding your pages.
Another similar option is Slim, which looks like this:
require 'Slim/Slim.php';
Slim::init();
Slim::get('/hello/:name', function ($name) {
echo "Hello $name";
});
Slim::run();
Example from their site.
Answer to Question 2
Something along these lines in your .htaccess file should work for your rewriting needs.
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)$ index.php?page=$1 [QSA,L]
1.for index.php?page=signin
$urlEnd=$_GET['page'];
require('path_to_file'.$urlEnd);//Require your file
header('Location: index.php?/$urlEnd');//WARNING!!! HEADER MUST go befor any echo's
Related
I'm quite a rookie with CodeIgniter, and as per title, I have troubles trying to setup a single controller for my application. It's a very simple static site with couple of pages like "home", "about" and so on...
I have this in my routes.php file:
$route['default_controller'] = "mycontroller";
$route['404_override'] = '';
$route['(:any)'] = "mycontroller/$1";
And this in mycontroller.php file:
// Home
public function index()
{
$data['page'] = 'home';
$this->load->view('template',$data);
}
// about
public function about()
{
$data['page'] = 'about';
$data['title'] = 'About Us';
$this->load->view('template',$data);
}
I'm working in a localhost environment, and the CI project is in this folder:
http://localhost/local/project/ci-tbs/
and I've specified it also in the config.php file for the base_url parameter.
Now what I'd expect pointing the browser to
http://localhost/local/project/ci-tbs/about
is to find the "About Us" page, instead I got a 404 error. Pointing to the base address corectly gives me the "Home" page.
What am I doing wrong?
Is it sensed to use a single controller istead of 1 per page? I'd totally do that in a quick way to fix, still I'm quite baffled by the fact that I can't understand what I am doing wrong and why it's not working. I'd like to simple set everything in one controller, one method per page.
I've already seen this topic asked here in SO, like using regular expressions in the route $route['(.*)'] = "mycontroller/$1";, but nothing really worked for my case wich I think is quite basic (so basic I'm sure my error is so gross that it will be quite embarrassing :P ).
Additional info:
I have in the folder an .htaccess file picked as is from the Html5 Boilerplate, tried with and without it but 404 is always there. I'm using XAMPP as local environment.
For answer
As mentioned by #Vincent Decaux in the answer, the deal to fix this was to add index.php in the url, the other interesting part is
Create your .htaccess file to "hide" index.php
This way I've resolved another small issue for the pages with missing findings for the assets files, so I used the following rule in the .htaccess file, redirecting all requests to the index.php file and excluding files in assets folder and images, along with robots.txt as suggested here https://stackoverflow.com/a/11846150/1262357
RewriteEngine on
RewriteCond $1 !^(index\.php|assets|images|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
hope this helps others with same problems I had!
As mentionned in my comment, it seems to work using :
localhost/local/project/ci-tbs/index.php/about
Create your .htaccess file to "hide" index.php.
i want to build a website with different views, but a stable header and footer - no problem so far. But i dont like the kind of urls i got at the moment with the php GET method.
My site at the moment works like this (what istn working properly):
$_page = $_GET['p'];
if ($_page == "city-sitemap"){ include "views/city-sitemap-view.php"; }
if ($_page == "place"){ include "views/place-view.php"; }
else { include "views/index-view.php";}
this isnt a very sweet solution but i dont know a other for now. I tried to use a mvc framework but failed dramatically. So everytime i add a link i use for example this "index.php?p=place" - not very nice.
The including of the views isn very smart as well? is there a better way?
I would like to use something like the rewriteEngine that the new url is like a folder.
Can you help me to find a better solution?
Thanks a lot
Page including
For the page inclusion, you can use a simple array to dynamically allocate your page to a specific name. As so:
$pages = array('city-sitemap'=>'views/city-sitemap-view.php',
'place'=>'views/place-view.php',
)
if(array_key_exists($_GET['p'], $pages){
include $pages[$_GET['p']];
}else{
include 'views/error.php';
}
This array should be added in a general configuration file. With this configuration if you want to display your city-sitemap-view.php view, you will have to write this url: http://www.domain.com/index.php?p=city-sitemap
Url rewriting
It is possible to rewrite an URL with a .htaccess file. Here is an example of code you would can to write in your .htaccess file.
RewriteEngine On
RewriteRule ^(.*)$ index.php?p=$1 [L,QSA]
An url that looks like this:
http://www.domain.com/index.php?p=city-sitemap
will be converted to this one:
http://www.domain.com/city-sitemap
There is something called the front controller that you should look into. You can write a very simple one yourself. It works in conjunction with URL rewriting. If for example your url looks like this:
/mypage.html
the url rewriter will reroute the request to index.php .
Index.php will then look at the URL and do somehting like this:
1) break the page out into string, ignoring .html extention
preg_match("\/(.*?)\.html", $_REQUEST['URI'], $matches);
$pageClass = $matches[1];
//$pageClass = "mypage"
2) look for and load a class named "Mypage.php"
$controller = new $pageClass();
3) call the run method on the page class, passing it all the request parameters
$request = new Request($_REQUEST);
$controller->run($request);
you can then do all the page specific stuff inside your controller class that is specific to the page.
At each simple step along the way, you will find you want to do more and more things like authentication, filtering, tracking, etc. You will get end up developing a front controller that is specific to your needs, as well as a base Controller class that does a bunch of standard stuff that all your controllers have in common.
As per my comment, i really think you should consider the framework i linked, (it is very logical) or any other micro framework, but if you really wish to do this yourself then you can handle your includes like so:
<?php //index.php
$requested_page=isset($_GET['p'])?$_GET['p']:'home';
//maybe have this included from pages.php for organization
$pages=array(
'home'=>'home_content.php',
'about'=>'about_content.php',
'contact'=>'contact_content.php'
);
include "views/header.php";
if(array_key_exists($requested_page, $pages)){
include "views/".$pages[$requested_page];
}else{
header('HTTP/1.0 404 Not Found');
include "views/error404.php";
}
include "views/footer.php";
This keeps your pages in a single array, and protects against arbitrary inclusion vulnerabilities.
For nicers urls, see The other users .htaccess rewrite rules
My website structure somewhat looks like below
css/
lib/
js/
index.php
profile.php
products.php
checkout.php
orders.php
invoice.php
I have added a codeigniter folder in there ...
codeigniter/application/
codeigniter/application/controllers/
codeigniter/application/controllers/mycontroller.php
and other files
I can access CodeIgniter stuff by going to mywebsite.com/codeigniter/mycontroller etc fine.
However, I want to get rid of /codeigniter/ part from the URL. So I was wondering if it is possible to create a whitelist of the files which are CodeIgniter specific? For example, if the URL is mywebsite.com/mycontroller then it does CI stuff otherwise it looks for the plain PHP code file. I have only a couple of CI controllers and loads other non-CI files.
Any ideas?
I think you could use .htaccess to rewrite URL's that don't contain .php, css, lib and js. Something like:
RewriteCond %{REQUEST_URI} !^(\.php|css|js|lib)$
RewriteRule (.*) codeigniter/index.php/$1
So:
http://example.com/css/test.css
stays
http://example.com/css/test.css
(as will all requests to css|lib|js. You can append more things here for the rewrite to ignore)
http://example.com/controller/method
becomes
http://example.com/codeigniter/index.php/controller/method
You can test it out here: http://htaccess.madewithlove.be/
More on rewriting: http://httpd.apache.org/docs/current/mod/mod_rewrite.html
Short-term Solution
You can start by simply converting the index.php file into a controller and name it whatever you wish:
<?php
class New_default_controller extends CI_Controller {
public function index()
{
// home page stuff here
}
}
Alter the route.php file and set your default controller so that simply visiting your site will trigger the proper controller:
$route['default_controller'] = 'new_default_controller';
Apply the instructions for Removing the index.php file
Now calls to www.mysite.com/profile.php will access the profile.php at your root and calls to www.mysite.com/new_future_page will call your new_future_page controller.
Please let me know if any of this is confusing or you get stuck.
Optimal Solution
I wanted to leave a comment above but this would have been impossible to show as a comment.
You will have to take your PHP files and put them in the controllers folder like this:
codeigniter/application/controllers/profile.php
codeigniter/application/controllers/products.php
codeigniter/application/controllers/checkout.php
codeigniter/application/controllers/orders.php
codeigniter/application/controllers/invoice.php
Please go through and do the Tutorial before continuing any further. Specifically the Static Pages section will help you in achieving your goal.
You will have to convert your current PHP files to follow the flow of CodeIgniter
I currently run a site where I want to give people the ability to make their own URLs. For example, here is my URL:
http://www.hikingsanfrancisco.com/hiker_community/hiker_public_profile.php?community_member_id=2
You see, it is named just by id, which is uninteresting and also bad for SEO (not that it matters here).
Ideally I want my site members to also have their names in the URL. How is that typically done? So in my case, it would be something like:
http://www.hikingsanfrancisco.com/alex-genadinik and have the id hidden.
Is that possible? Any advice would be appreciated!
Thanks,
Alex
you need router, see https://stackoverflow.com/questions/115629/simplest-php-routing-framework
Generally this is accomplished via the use of an htaccess file on a server with mod_rewrite (most Linux servers). An example might be like:
Options -Indexes
RewriteEngine On
RewriteRule ^([0-9a-zA-Z\-]+)$ $1.php
RewriteRule ^/(alex[\-]genadinik)$ /hiker_community/hiker_public_profile.php? community_member_name=$1
This implies that your hiker_public_profile.php script will need to accept "alex-genadinik" as $_GET variable "community_member_name," and then query the database via the name instead of the ID.
So you'd take the above code, save it in a file called ".htaccess," and then upload it to the root directory of your website. Learning regular expressions is recommended.
Code Igniter is a great MVC framework which provides configuration derived routes, which can easily be configured to send all requests through a common controller, where content can be dynamically pulled from a database and rendered.
Here is an example of a basic routing rule, which excludes request for users, students, and lessons, but routes all other request to a common content controller.
So if you request http://mydomain.com/hiking-and-camping-info, the url would be parsed, and hiking-and-camping-info would be looked up in the database and the related content pulled down.
Routing configuration:
$route['^(?!lessons|students|users|content).*'] = 'content';
and the content controller then grabs the url segment and finds the matching content and loads it:
class Content extends Controller {
function __construct() {
parent::Controller();
$this->load->model('Content_model', 'content');
}
function index() {
$content_url = $this->uri->segment(1);
$data['content'] = $this->content->get_content_by_name($content_url);
$this->load->view('content', $data);
}
}
I am looking to create a simple php script that based on the URI, it will call a certain function.
Instead of having a bunch of if statements, I would like to be able to visit:
/dev/view/posts/
and it would call a 'posts' function I have created in the PHP script.
Any help would be greatly appreciated.
Thanks!
Are you using a framework? they do this sort of thing for you.
you need to use mod_rewrite in apache to do this.
Basically you take /dev/view/posts
and rewrite it to
/dev/view.php?page=posts
RewriteEngine On
RewriteRule ^/dev/view/posts/(.*)$ /dev/view?page=$1
in view.php
switch($_REQUEST['page'])
{
case 'posts':
// call posts
echo posts();
break;
}
EDIT made this call whatever function is called "page"
You probably want to use a framework to do this because there are security implications. but very simply you can do this:
if (array_key_exists('page',$_REQUEST))
{
$f = $_REQUEST['page'];
if (is_callable($f))
{
call_user_func($f);
}
}
Note there are MUCH better ways of doing this! You should be using a framework!!!
Take a look at the call_user_func function documentation.
$functions['/dev/view/posts'] = 'function_a';
$functions['/dev/view/comments'] = 'function_b';
$functions['/dev/view/notes'] = 'function_c';
$uri = '/dev/view/comments';
call_user_func($functions[$uri]);
What you are looking for is a form of URL rewriting on your web server. For instance, if you are using Apache you should lookup mod_rewrite. An example of what your rule might look like:
RewriteEngine On
RewriteRule ^/dev/view/posts/(.*)$ /posts.php?id=$1
But I'm assuming that you are wanting to have a trailing post ID or similar so that you can use this for multiple posts URLs.