I have a scenario where I want something similar to Codeigniter.
In Codeigniter my url is like:
http://www.example.com/filename/methodname
Now I want similar thing but using plain core PHP and .htaccess.
How is that possible ?
I want to have a index.php inside my folder and then redirect the http requests accordingly.
Searching the web I found this :
RewriteEngine on
RewriteRule ^([a-z0-9_-]+)\.html$ index.php/page/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|asset|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
But I have little knowledge of .htaccess and don't know how this could help.
So I want an answer with example to understand how this can be achieved using .htaccess.
What would I need to do on my PHP side ?
Routing
Having urls like /filename/methodname is generally called routing. You have half of it done already; what you show in .htaccess is the part that will redirect all traffic towards an index.php file.
# starts rewrite engine
RewriteEngine on
# redirects direct .html page calls to their corresponding pages
RewriteRule ^([a-z0-9_-]+)\.html$ index.php/page/$1 [L]
# for anything that is not a file
RewriteCond %{REQUEST_FILENAME} !-f
# and for anything that is not a directory
RewriteCond %{REQUEST_FILENAME} !-d
# except if it's a robot
RewriteCond $1 !^(index\.php|asset|robots\.txt)
# send all that to index.php
RewriteRule ^(.*)$ index.php/$1 [L]
That index file will then parse the url and call relevant handlers with relevant arguments based on what matched.
How to create one such parser, or router, is beyond the scope of a single answer, but basically depends on the use of $_SERVER['REQUEST_URI'] and an array of urls with their corresponding handlers.
Solution
This is a "solved problem", and while it is interesting to implement such a thing by yourself, I would recommend simply to use a library that does it for you. I personally use Fast-Route, a pretty straightforward library that allows for customization in the way you handle routes, but if you google for "php routers" you will find plenty of them.
Of Filename/Methodname
(opinions follow from here on)
This point should be rethinked. While with psr-4 (and psr-0, and probably psr-whatever) the correspondance between a specific class and its file is that the file is named after the class it contains, I believe it better to not think about this as filename/methodname but rather section/action, or whatever speaks best of what the url actually does.
Moreover, if you start using namespaces (which you should do if your oop code becomes slightly more complicated than a hello world page), you obviously won't pass full namespaces in urls, and they actually are irrelevant to your users.
Related
I have a question concerning an API that I am developing and I have just started asking myself the following question: As a rule, to reach the main file, you have to reach it in the following way api.domain.com/index.php/users/id/profile/... but many sites allow you to avoid calling the file index.php but put the "query" directly. My question is, what should I do in order not to enter the file name, since if I don't put index.php it goes missing because it sees the query as folders
You could use .htaccess file.
As an example, you may add this to your .htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]
And then use some sorte of routing (like FastRoute or Laravel routes) to redirect the user where you wanted. This way, you could call api.yousite.com/users/id/... and it'd go through the index.php anyway.
You can also take a look at this or this.
I'm currently writing a PHP app and am about to create various controllers. Currently I have one controller with certain method, so the URL looks like this:
http://somewebsite.com/index.php?c=controller&a=action
It's being rewritten to this:
http://somewebsite.com/controller/action
With this .htaccess file:
RewriteEngine On
RewriteRule ^([a-z]+)/([a-z]+)$ index.php?c=$1&a=$2 [NC]
What I want to achieve is the ability to rewrite URL with more than one controller (the more, the better), possibly in random order. Is there a more convenient way than rewriting every possible combination of URL parameters?
Many frameworks (Codeigniter, WordPress, Laravel, etc.) use an .htaccess file similar to the following:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
This rewrites all incoming URLs to be handled by the index.php file. You can then use $_SERVER['REQUEST_URI'] variable to get the exact request URI, parse it, and then handle it how you want.
if you're going for an arbitrary routing scheme, probably your best bet is to just pass the entire url string e.g. ^(.+)$ to index.php and let your php application split the string based on '/' and handle the array however makes sense for your application
I have no idea how htaccess works, and the theory of it just wont connect in my head no matter how many tutorials I read.
I am building a simple MVC framework which works beautifully, except I don't like the way I am dealing with htaccess. To rewrite the URL's properly, this is what I am doing:
RewriteEngine on
RewriteRule ^users/([^/]+)(/([^/]+))?$ controller/users.php?method=$1¶m=$3
If I add a new controller, I then have to go into htaccess and add a new line:
RewriteRule ^access/([^/]+)(/([^/]+))?$ controller/access.php?method=$1¶m=$3
Is there a way to make it all automatic with wildcard fields so I don't have to access htaccess every time I do an update?
You can move logic for parsing query string into your framework/application. For this, make you rewrite rule like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
In this case, any request to server will be processed by index.php (if static file with same name not exists). And $_SERVER['REQUEST_URI'] will be equal real request uri - just parse it and use for your logic.
For example, if send /user/registry request with that .htaccess
$_SERVER['REQUEST_URI'] => '/user/registry'
You can try this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)(/([^/]+))?$ controller/$1.php?method=$2¶m=$4
The two extra rules will skip the rewrite if the file or directoy referenced actually exists on the disk, eg: it won't try to rewrite requests for http://site.com/images/logo.jpg.
I'd redirect all URIs to index.php and allow another well established MVC concept handle the controller dispatching: Routers.
Many (most) MVC (and some non-MVC) applications use this by default because it allows advanced routing techniques (not only controller/action structured URIs).
Controllers can "register" (new) routers and set their priorities. The application can run all routers (in order of priority) until one router finds a matching route (and is able to discern which controller should be used).
For example many blog-like applications will need SEO friendly URIs meaning something like category/subcategory/subsubcategory/blog-article.html. Many cms-like applications will need the same for their hierarchical pages: top-level-page/mid-level-page/low-level-page.html. As well as many eCommerce applications will want that for their products: category/subcategory/product.html.
The above URIs need a router which will check the database to find out which article/page/product has that URI-key.
I'll be signing businesses up to advertise on my website, and I want them to have a direct URL for their customers to go to.
Like, instead of www.website.com/page.php?id=324234234,
I want to have www.website.com/businessname
Is there a simple way to do this? I've searched and seen a whole bunch of different things people are trying to do but I haven't seen anything that's the same as what I want to do.
I'm using a VPS, and I want to make sure that I don't open up permissions so that anyone can get in there and mess things up.
Also, these users will not be signing themselves up. I will be doing that.
The simplest way to get my end result is what I'm looking for. Thanks!
Basic URL rewriting could work.
Add to your .htaccess file
RewriteEngine on
RewriteRule ^(.*)$ page.php?businessname=$1 [L]
Then use PHP to rewrite the businessname to the ID of the company / find the data.
Of course .htaccess rewrite rules is a complete science if you need more complex rewriting...
Re-iterating what jtheman said with a little more explanation:
Create a file named .htaccess with the contents:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ page.php?businessname=$1 [L]
You need, of course, the ability to have directory level .htaccess enabled - you're using a VPS so you should be able to do this if it is not already enabled.
So let me explain what each line will do.
RewriteEngine on
Turns on the ability to URL re-write
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Tells Apache not to re-direct files that exist in the directory already
RewriteRule ^(.*)$ page.php?businessname=$1 [L]
This is where the magic happens.
^(.*)$ this part is like a regular expression match. It will tell Apache to collect any URLs that have any characters within them and redirect them to page.php?businessname=(.*)
So, if you post:
www.website.com/stackover
It will really be sending: www.website.com/page.php?businessname=stackover
Then you can just use $_GET[businessname] to dynamically update the page.
Hope this helps!
I have been experimenting with the lightweight NiceDog PHP routing framework, which routes like this:
R('entries/(?<id>\d+)')
->controller('Entries_Controller')
->action('show')
->on('GET')
Now the .htaccess file is set up to do this redirect like so:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
My problem is when I want to make a URL to somewhere, it seems impossible to do so.
Say I've requested the page entries/5, and on that page I would like to link to another entry entries/6:
Next Entry
This resolves to the address http://localhost/folder/to/project/entries/5/entries/6
Not what I want.
The href /entries/6 would link to http://localhost/entries/6
Also not what I want.
To work around this, I created a function to handle this problem:
function url($route) {
return "http://localhost/folder/to/project/$route";
}
So I can now write
Next Entry
which now links to http://localhost/folder/to/project/entries/6, which is exactly what I want.
However, I have to do this for EVERY in-site link, and it seems like there could be a better solution that doesn't involve an externally created URL.
Is there a "better" way to fix this problem? Is this a "common" problem with PHP frameworks? (It seems it would be)
The easy alternative would be to use <base href="http://example.org/your/project/index" /> in your page templates <head>. But that's basically like having full URLs generated. And yes, it's also valid for XHTML and still in HTML5.
I don't know about NiceDog but other frameworks I have used have a built in function that can convert a route to the corresponding URL.
For example in Symfony this would look something like:
Link Text
The routing system will then reverse resolve this into the URL relative to any root you set in the config.
Could you use:
RewriteBase /folder/to/project/
in your htaccess file making
RewriteEngine On
RewriteBase /folder/to/project/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html