I was wondering how one could make codeigniter style url segments on a project.
Aside from an htaccess rule to capture the segments, how can this be done in PHP?
After snooping around the codeigniter source code, i could not find any reference to an htaccess file that captures the usage.
Any idea on how this can be done?
Assuming you are passing ALL requests to index.php via Apache mod_rewrite or Nginx:
// Get the current URL path (only) and convert encoded characters back to unicode
$path = rawurldecode(trim(parse_url(getenv('REQUEST_URI'), PHP_URL_PATH), '/')));
// array merge with defaults
$segments = explode('/', $path) + array('home', 'index');
//First two segments are controller/method
$controller = array_shift($segments);
$method = array_shift($segments);
// #todo serious security checking here!
// Finally, load and call
$controller = new $controller;
$controller->$method($segments);
Your controller would look like this
class Home
{
public function index($params)
{
print_r($params);
}
}
What you do is set up one single url param in htaccess, and then use a string splitting method to retrieve a model, controller, and view from that string which will then call a model class, a controller class, and then render the data into a view. the transformation would be something like the following:
mysite.com/index.php?url=/tasks/all => mysite.com/tasks/all
which calls the task model, which then calls the function called "all()" inside of the tasks controller.
As soon as this site goes back online, do look at the htaccess portion of the tutorial -- he did a good job of showing how its done http://www.henriquebarroso.com/how-to-create-a-simple-mvc-framework-in-php/
You still need something to "forward" all virtual requests to a physical file.
The idea is that any URI that doesn't match a physical file or folder on disk is rewritten (usually through mod_rewrite) to your index.php file (it's usually your index file so a direct call to the index works too), and it appends the URI to the path or as a query string parameter:
RewriteCond %{REQUEST_FILENAME} !-f # Not a real file
RewriteCond %{REQUEST_FILENAME} !-d # Not a real folder
RewriteRule ^(.*)$ index.php/$1 [L] # Rewrite to index.php, with a leading slash, followed by the URI
Alternatively, you can use a standard error document handler (still in .htaccess or apache config, but no need for mod_rewrite!):
<IfModule !mod_rewrite.c>
ErrorDocument 404 /index.php
</IfModule>
Now that control is passed to uniformly to an index.php file, you need a router mechanism to match the route to the correct controller. Ideally, you'd have a list of static and dynamic routes. Static routes are direct matches to the URI, and dynamic would be regular expression matches. Check your static routes first, as it's as simple as a single hash lookup, while you'll have to loop through all the dynamic routes.
For performance, it's nice to put your more common dynamic routes at the beginning of the list, and the obscure ones at the end.
Using the .htaccess file to employ mod_rewrite to rewrite the base of the url is essential to this. Otherwise, the browser will treat each segment as a supposed folder or file (depending on whether or not you have a trailing /)
once you have that, however, you can simply use the method described in this post:
how do i parse url php
Related
I have 2 controller classes in my application named Localhost/electronics.
The URL "Localhost/electronics/cameras" goes to
"localhost/electronics/home/details/cameras".
This is happening because of the rule
$route['(:any)'] = "home/details/$1";
2nd controller class specifics() and it's method showspecifics() is accessed through URL
`"localhost/electronics/specifics/showspecifics/camera1.`
How can I do the following?
Only with the help .HTaccess file, I want to.. be able to access the second class specifics() using URL
`"localhost/electronics/camera1` .
I am aware that using
`$route['(controllername/:any)'] = "specifics/showspecifics/$1";`
is a possible way close to achieving the clean URL but it's not what I want.
Please advise as to how to use htaccess to accomplish this.
Any idea is greatly appreciated.
Usually, you would capture the final part of the URL and then rewrite the request, e.g.
RewriteCond %{REQUEST_URI} !^/electronics/specifics/showspecifics/
RewriteRule ^electronics/(.+)$ /electronics/specifics/showspecifics/$1 [L]
The RewriteCond is there to prevent a rewrite loop.
This doesn't work with CodeIgniter however, because CodeIgniter looks at REQUEST_URI to determine the controller and method to serve this request. But REQUEST_URI isn't changed by the RewriteRule and remains /electronics/camera1, and CodeIgniter doesn't find an appropriate controller.
To change REQUEST_URI, you had to redirect instead of rewrite, e.g.
RewriteRule ^electronics/(.+)$ /electronics/specifics/showspecifics/$1 [R,L]
but this also changes the client's URL bar, which isn't desired in this case.
So, there's no way to achieve this with .htaccess and CodeIgniter.
To do this in CodeIgniter, you would use appropriate routes in application/config/routes.php like
$route['(cameras|smartphones|computers)'] = 'home/details/$1';
$route['(:any)'] = 'specifics/showspecifics/$1';
This handles the few categories by controller and method home/details, and everything else by the controller and method specifics/showspecifics.
I have a task that's been giving me considerable trouble. Any help much appreciated.
I am using an MVC framework in PHP (codeigniter) and all requests are sent through a root index.php file.
I am trying to pass another site's url as a parameter to the defualt controller. Like this:
http://mywebsite.org/https://google.com
Apparently this can be done using with a mod_rewrite rule in the root .htaccess file
so ideally i would be able to use the 'http://google.com' as a parameter in my controller.
it requires some regexp and rewriteRule knowledge. Been struggling for a while.
Any ideas?
This would be a rewrite rule for the .htaccess:
RewriteRule /(.+) /index.php?url=$1 [QSA]
http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_qsa
With codeigniter this should do the job:
http://www.codeigniter.com/user_guide/general/urls.html?highlight=uri%20segments
The segments in the URL, in following with the Model-View-Controller approach, usually represent: example.com/class/function/ID
The first segment represents the controller class that should be
invoked.
The second segment represents the class function, or
method, that should be called.
The third, and any additional
segments, represent the ID and any variables that will be passed to
the controller.
And here is explained how:
Passing GET parameters through htaccess + Codeigniter
I have a problem with routing like this:
$route['(/[a-z]{2}/)'] = 'locale/somepage';
And in .htaccess
RewriteEngine on
RewriteBase /
RewriteRule ^(/[a-z]{2}/)$ /index.php/locale/somepage
I need replace first section of url (class or controller) and call an another controller. For example, I need to url as /en/page will call controller locale, but url need not be changed.
This code is not working. And if I try use only routes.php or only .htaccess, it not working too.
How I can make it work?
I think you've written your htaccess regexp rule wrong. You don't need to write it as a PHP regexp rule, try to rewrite it without the slash in your htaccess:
RewriteRule ^([a-z]{2})/page$ /index.php/locale/somepage
This will send any http://mypage.com/en/page to index.php/locale/somepage.
With that rule, CI will receive the url index.php/locale/somepage. At that point, CI will go to routes.php and will check if there are any rule to call a specific controller. If not, it'll try to go to a controller called locale, to load a method called somepage.
So, you don't need to use routes.php to modify again the apache url that you're receving to call another controller.
Im giving support to an already deployed php application, but the way it works is new to me, and I have no idea how it does what it does.
Basically, a php method is called using a path-like syntax to retrieve data, for example:
<?php
// .....
$json = Request("http://_server/myfolder/abc/default/mymethod?data=something");
// Now $json var has some information.
?>
The odd thing is how methods are structured. Up to folder 'myfolder' physical path exists in linux 'server', you know ".../apache/htdocs/myfolder/" but thats IT. Further than that, physical location of code is within a different folder structure where default/mymethod matches NO folders at all.
By digging deeper, I found that mymethod corresponds to the PHP method located in:
apache/htdocs/myfolder/protected/modules/abc/controllers/defaultcontroller.php
And inside defaultcontroller.php there is something like this:
<?php
// ....
Class DefaultController {
// ....
Public Function actionmymethod { // Notice the name of mymethod has 'action'
// more code
return $response;
}
}
?>
Im 100% sure that method is fired when running the Request call, but my I dont know how it is done.
My question is:
How the setup of this is done? There must be some place where you relate:
"http://_server/myfolder/abc/default/mymethod" with "actionmethod"
but where and how?
I need to make a copy of this running, so I can call my copy with something like this:
"http://_server/FOLDERCOPY/myfolder/abc/default/mymethod"
I already made a copy to the new structure, but when calling it, server cant find the new method/path :(
EDIT***
I found this in htaccess located at /myfolder/
RewriteEngine on
RewriteBase /myfolder/
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
I modified the copy inside /FOLDERCOPY/myfolder, but it seems is not working :(
RewriteEngine on
RewriteBase /FOLDERCOPY/myfolder/
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
Thanks
Not every url is mapped 1:1 to the server's filesystem.
Apparently, there should be a php script inside .../apache/htdocs/myfolder/, most probably an index.php. There should also be some rewrite rules, probably in a .htaccess file, that translate urls under http://_server/myfolder to that script, tranforming the remaining part to parameters (either a query_string or a path_info).
From this point on, php takes over. The structure implies the existence of an MVC framework. This framework appears to support modules, one of them being abc, whose default controller's mymethod method is called to handle the request. So the url structure is like this:
http://server/site/module/controller/method?params
Look for a config file under .../apache/htdocs/myfolder/ (config.php?). It will contain rules as to the modules' location and the mappings (routing) to controllers. Then again, there may be a global site config, as well as one for each module...
I have my routes.php as
$route['home'] = 'pages/home';
$route['login'] = 'pages/login';
$route['default_controller'] = 'pages/home';
and the controller pages.php as
class Pages extends CI_Controller {
public function home() {
$this->load->view('templates/header');
$this->load->view('pages/home');
$this->load->view('templates/one');
$this->load->view('templates/two');
$this->load->view('templates/footer');
}
public function login() {
//if ( ! file_exists('application/views/templates/'.$page.'.php')) {
// echo "no file";
// }
// $data['title'] = ucfirst($page);
$this->load->view('templates/header');
$this->load->view('templates/login');
$this->load->view('templates/footer');
}
}
Pre: I have just started with CodeIgniter and what I got from basic tutorial and after reading many stackoverflow answers is that a call for domain/login will be routed to function login in Pages class(controler) as per the the routing rule $route['login'] = 'pages/login';
The Problem: This simple code is showing 404 error. I am not getting it why it is so, as all the files are too present in templates folder. Also the normal call to domain works fine but if I call domain/home, again I get 404 error. Kindly help me what I am doing wrong.
So I am a bit new to CodeIgniter as well so I apologize at being so slow on this. The problem you are facing is that you haven't put in index.php. Your URL has to be domain/index.php/login. If you don't want to add index.php to every call then you must do the following:
add a .htaccess file in your application folder and have it look something like this:
<IfModule mod_rewrite.c>
# activate URL rewriting
RewriteEngine on
# the folders mentioned here will be accessible and not rewritten
RewriteCond $1 !^(resources|system|application|ext)
# do not rewrite for php files in the document root, robots.txt or the maintenance page
RewriteCond $1 !^([^\..]+\.php|robots\.txt)
# but rewrite everything else
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
ErrorDocument 404 index.php
</IfModule>
Turn on mode_rewrite (How to enable mod_rewrite for Apache 2.2 or https://askubuntu.com/questions/48362/how-to-enable-mod-rewrite-in-apache)
Restart your server
This will forward all domain/login requests to your front controller (index.php). The line RewriteCond $1 !^(resources|system|application|ext) will allow you to make certain folders NOT get rewritten. So if you have a folder under application named "resources" instead of it getting forwarded to domain/index.php/resources it will simply go to domain/resources.
In actuality without an .htaccess file the process is like this:
Check for domain/front_controller/route pattern in the URI and see if route exists and forward appropriately
By doing domain/login you were not following the pattern and so a 404 was delivered. Adding the front_controller (index.php) to the URI makes it follow the route pattern and gets forwarded to your route config.
Some people think the front controller in their URI is "ugly" so they add in a mod_rewrite which basically adds in the front_controller to the URI every time that directory is accessed. This way they can stick to domain/controller/action. This is also considered more secure as the only directories that can be directly accessed are the ones that are specifically stated in the rewrite.
Got it now !
Actually defining the
base_url = 'mysite.com'
in config.php just works for calling the default_controller in routing rule, and so your while mysite.com call will work normal and show you the home page, *interpreting default_controller* routing rule, but any calls for mysite.com/xyz will fail, even you have a function xyz in the main controller with routing rule as $route['xyz'] = 'pages/home',
as rest all URL calls have to be made as
domain/index.php/controller/function/arg,
and as suggested by #Bill Garrison, and also from the developer user guide of codeigniter, one should write rules in the .htaccess to remove index.php from domain name, and the url to router will then work as normal !!
For people reading out, one big advice well read the documentation thoroughly before firing the doubts. :)