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
Related
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.
I am deciding to create separate profile links for each user who registers on the website. I am using the .htaccess file RewriteRule to achieve this. The url I want to achieve should look something like www.domain.com/username. (I don't want www.domain.com/users/username)
Now the problem is, if I add a rule like RewriteRule ^(.*)$ /users.php?username=$1
it will matchup all URL addresses for www.domain.com, which may direct to any path. Even if I would like to visit www.domain.com/about page, it will be redirected to
www.domain.com/users.php?username=about, which I don't want. (Even if the requests was www.domain.com/products/abc)
I could apply filters in my users.php to filter such usernames, or if a username is not found in database, redirect to the page, but this means I have to change filters every time I decide to add a new page in my directory (in this case, any). Also, all traffic will be directed through 1 page, which may cause a performance problem.
Please suggest a way to achieve this, as There are websites that work like this. A possible RewriteRule or PHP code to achieve this.
You can use this rule in your root .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(\w+)/?$ /users.php?username=$1 [L,QSA]
I always use just simple rewrite as below:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)(.*)/?$ index.php
All traffic is redirected to index.php and using php I can run specific controllers depending on url. You should also think about. Almost all frameworks use such rule.
Then in your PHP file you should examine
$_SERVER['REQUEST_URI']
variable to route request to specific controllers
I have web site in core php and I want to make my SEF URL.
In my web site for transferring control from one page to other i have used something like
header("Location: edit.php?id=12");
I read one article but couldn't get it how to implement it.
Link of article
So how i can make url to read like "mysite.com/usr/edit"
I read lot on google i got the idea that i need to do something in .htaccess but i dont know what needs to do with url in php so i dont have to change major code in site.
Thanks in advance.
You can do it with the .htaccess code given below:
RewriteEngine On
DirectoryIndex index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
after creating .htaccess file with above code. You will have all the stuff after the file name ex. "/usr/edit" in the GET parameter $GET['url']. After that you can do anything.
Here is the working example of my MVC framework: https://bitbucket.org/ManthanB/my-framework/
You can contact me for further information.
Let's say I have the project folder as follows:
folder/models
folder/view
folder/controls
folder/public
folder/library
Now let's say that the site folder is folder/public/ and inside that folder there's just one file called index.php. This file handle all the site page request via the GET parameter index.php?page=user for example will call the user.php file of the application in another folder. The point is that I'd like that an URL such as:
www.site.com/index.php?page=user&id=1
became
www.site.com/user/id/1
How can I do that?
This was taken from CakePHP .htacess rewrite rule:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
It will render everything under your host
http://www.site.com/* --> http://www.site.com/index.php?url=*
from here your index.php could parse $_GET['url']
//e.g browser requests www.site.com/user/id/1
$url = $_GET['url']; // user/id/1
$params = explode("/",$url); // array(0=>"user",1=>"id",2=>"1")
RewriteRule ^user/id/([0-9]+)$ index.php?page=user&id=$1
But it sounds to me that you should use so called router, redirect all trafic to index.php...
http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/ (check out this link)
In your case there is no point in using /id/, but here you go:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/id/(.*) index.php?page=$1&id=$2
Or what's a way better approach:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php
Then handle the request in your index.php file by checking $_SERVER['REQUEST_URI'] against the patter you dream up.
Without apache rewrite rule, a micro framework named Slim can makes routing and templating for your php project. You'll define your routes only in index.php file. Like ;
Slim::get('/', function () {
Slim::render('index.template');
});
You will be implementing what is called the Front Controller pattern. If you Google that you will find several php implementations. I thought this series on building your own php framework was good.
http://fuelyourcoding.com/php-frameworks-just-roll-your-own-part-1/
Are you using Apache as web server?
If yes you can use *mod_rewrite* to accomplish that.
I have not done this myself, so I can't give you detailed instructions, but searching with google, using a search string like "mod_rewrite examples" lands you a lot of seemingly good tutorials.
The main navigation of my site is coded like this:
<li>'.$value.'</li>'."\n";
But I would like the URL of the links to look like domain.co.nz/pagename, not domain.co.nz/index.php?pageId=pagename
How would you recommend I accomplish this?
Something like this should work:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?pageID=$1
First line turns on mod_rewrite. Second line sets the base URL to / (it's annoying, but you have to set it to the base path you're dealing with). Third and fourth lines make sure the request doesn't exist as a file, or as a directory. And the last line is the actual magic; basically it searches for "anything", captures what it finds in $1, and "rewrites" the URL to index.php?pageID=$1. If you learn to use regexes, you can do much more complicated things as well.
Yes, you can accomplish this with a .htaccess RewriteRule. In your .htaccess file, include:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) index.php?pageId=$1
This means:
If the REQUEST_FILENAME is not a valid file, redirect the entire URL to index.php?pageId=the entire URL
You'd then change your navigation to:
echo "<li>'.$value.'</li>'."\n";
Edit: I moved Trivikrtam's edit inline, see above. The RewriteRule should be index.php?pageId=$1 not /index.php?pageId=$1. Thanks #Trivikrtam!