How to have clean URL's in PHP - php

Is there any way I can have good looking URL in PHP? any default php URL would look like this: http://example.com/something/?post=something But Is It possible to have It like this: http://example.com/something/user Is It possible to remove ?post= without using .htaccess
Here is some example code that I have been working on, Which on click of a post It would access my database and load the content:
<?php
if(!isset($_GET['post'])) {
$q = mysql_query("SELECT * FROM posts WHERE postID='something'");
} else {
$id = $_GET['post'];
$id = mysql_real_escape_string($id);
$q = mysql_query("SELECT * FROM posts WHERE postID='$id'");
}
$p = mysql_fetch_object($q);
?>
Thank you for your Time!

To get clean URLs you'll have to use mod_rewrite module, but you can minimize it's use, if you leave url parsing to your own script and have only one entry point. Look how it's made in WordPress:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
So if there's no real file or directory that is requested in URL, each and every request is redirected to index.php and then parsed by some internal route mapping script.
There's an example of such script in similar question.

I suggest for having clean URL use one of php frameworks which default have this ability.
if you want to use pure php you should use a Router in your project which means you should write your own php framework.
have you ever worked with any php framework??
I suggest using laravel or cakephp for entry point of learning php frameworks.

You need to define a Router and Dispatcher in your project.The Router extracts url and dispatcher calls that function related to url.in the other word,you should impelement frontcontroller design pattern in your project.I suggest check this tutorial
http://www.sitepoint.com/front-controller-pattern-1/

Related

Joomla-like url rewrite

I know that similar questions were already asked, but i could not find any information for my specific "problem".
What i want to do is the following in a very dynamic way, which means that a "SuperUser" should be able to define new routes in a admin interface:
If a user enters http://www.example.com/nice-url/
he should get redirected to http://www.example.com/category.php?id=123 without changing the url.
Now there are a few ways i can achieve this. Either i use .htaccess like this:
RewriteEngine on
RewriteRule ^nice-url category.php?id=123 [L]
This works, but is not very dynamic. I would need to let a php script append new rules at the bottom which is not something i would like to do.
Or this:
.htaccess
FallbackResource /process.php
process.php
$path = ltrim($_SERVER['REQUEST_URI'], '/');
$elements = explode('/', $path);
if(count($elements) == 0) {
header("Location: http://www.example.com");
exit;
}
$sql = sprintf("SELECT Target FROM urlrewrites WHERE Source = '%s' LIMIT 1", array_shift($elements));
$result = execQuery($sql);
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
$target = $row['Target'];
header("Location: ".$target);
exit;
This also works, but sadly the url in the address bar gets changed. Is there a way in the middle of both? Having the flexibilty of PHP and the "silentness" of RewriteEngine? How do great CMS like joomla do it? Do they generate a htaccess file for each new page you create?
Thanks!
You can have this code in root .htaccess:
RewriteEngine on
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ category.php?uri=$1 [L,QSA]
PS: Note this will route /nice-url to /category.php?uri=nice-url. Then inside category.php you can dip into your database and translate $_GET['uri'] to id.
It would be more dynamic if you use regular expressions. That's how it works in CMS systems like Joomla. Good idea is to install Joomla with 'nice' URLs on and look over .htacces file to get to know how does it work.
You can start here:
http://www.elated.com/articles/mod-rewrite-tutorial-for-absolute-beginners/

vanity profile urls in php mvc not working

I am making a social networking site where I have created my own PHP mvc but I am having problems in url rewriting. My mvc works this way.
If this is the domain www.example.com/manage/posts/11111 , manage is the class, post is the method in that class & 1111 is a parameter.
The problem is that I cannot create vanity profile urls since they will not work. I want each user to have vanity profile url ie www.example.com/username but this will search for a class named username.
Kindly advise me on how
a) I can achieve vanity profile urls such as www.example.com/username without adding anything such as www.example.com/users/username.
I know there a other PHP MVCs but I just want to use my own
This is my current htaccess code::
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ index.php?ref_url=$1 [NC,L,QSA]
</IfModule>
I don't know why all people try to build their own frameworks there are so many really good frameworks that have a look at security and many more. But ok i think your problem is your rewrite rule.
RewriteRule ^(.*)$ index.php?ref_url=$1 [NC,L,QSA]
Normally you should rewrite all your input to a given file and parse the url and call the controller you need. To get a better understanding take a look at the Symfony2 Routing component.
http://symfony.com/doc/current/components/routing/introduction.html
You should first create a router to route your urls to controllers/classes. I will prefer klein router or FastRoute for its simplicity.
After placing a router do what u want:
(Example)
$router=new Router;
$router->addroute("/[:username]",
function(){
//Bring UserAccount Details from DB using [:username]
}
);
$router->addroute("/manage/posts/[:id]",
function(){
//Get Post details using [:id]
}
$router->dispatch();
**NB:**This is only a basic representation of usage of a router

php router - variable url

Hello I was trying to come up with the solution to my problem, but I just was not able to. So here is my problem:
What I used was a .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.+(.*)/(.*)$ ./index.php?mesto=$1&den=$2 [QSA,NC,L]
It will display the url well. as www.site.com/CITY/DAY for example ../Prague/30.3.2014 but i need it to be more complex.
What I need is to have additional parameters, such as Bar or Restaurant in the url for example www-site.com/Prague/30.3.2014/p/bar/restaurant and other time I might have www-site.com/Prague/30.3.2014/p/pizza/bar
That part I have no idea how to do, because I have 5 different parameters
I imagine that the raw url would look this index.php?city=Prague&day=30.3.2014&p1=0&p2=0&p3=0&p4=0&p5=0 where p1 to p5 are the parameters being active (0 not 1 yes).
I don't understand how to detect what parameters are active and how to properly display the pretty url. Could you please help me?
Use
RewriteRule ^(.*)$ ./index.php [QSA,NC,L]
This will redirect all your requests to a single index.php that parses the uri with something like this:
<?php
// Example URI: /florence/30-06-2009
// Remove first slash from REQUEST_URI
$uri = substr($_SERVER['REQUEST_URI'],1);
// Get an array with portions between slashes.
$splittedURI = explode("/", $uri);
// Here you get your city (or anything else that you want)
$city = array_unshift($splittedURI); // In example, $city = "florence"
// Remaining itens in $splittedURI are the arguments/parameters to your page
// Like this:
$date = $splittedURI[0]; // In example, $date = "30-06-2009"
?>
Remember that this is just and example, and you should do additional verifications to avoid PHP exceptions.
If you need complicated routing (and if you sure you want to create your own router instead of using a ready solution as ZF, Symfony etc.) you're better off just passing the whole request uri to a php router object. There you can as complex router logic as you need.
So basically, loose the parsing in the rewrite rule:
RewriteRule ^(.*)$ ./index.php?route=$1 [QSA,NC,L]
Then you can let the index.php create a router object that can parse the route parameter and delegate the job where it needs to.
I'd recommend reading up about existing routing solutions though.

URL Routing using RewriteRule

I am trying to create my own PHP MVC framework for learning purpose. I have the following directory structure:
localhost/mvc:
.htaccess
index.php
application
controller
model
view
config/
routes.php
error/
error.php
Inside application/config/routes.php I have the following code:
$route['default_controller'] = "MyController";
Now what I am trying to achieve is when any user visits my root directory using browser I want to get the value of $route['default_controller'] from route.php file and load the php class inside the folder controller that matches with the value .
And also if any user tries to visit my application using an url like this: localhost/mvc/cars, I want to search the class name cars inside my controller folder and load it. In case there is no class called cars then I want to take the user to error/error.php
I guess to achieve the above targets I have to work with the .htaccess file in the root directory. Could you please tell me what to code there? If there is any other way to achieve this please suggest me.
I have tried to use the .htaccess codes from here, but its not working for me
It all sounds well and good from a buzzword standpoint, but to me this is all a little confusing because I see PHP's model as an MVC model already. It's providing the API for you to program with and deliver your content to your web server Apache and your database (something like MySQL). It translates the code(model) for you into HTML(view) ... provided that's what you intend, and you're supplying code as the user input (control). Getting too wrapped up in the terminologies gets a little distracting and can lead to chaos when you bring someone in to collaborate who isn't familiar with your conventions. (This should probably never be used in a production environment for a paying gig.)
I can tell you that on the page that you referenced they guy's .htaccess file needs a little work. The [L] flag tells mod_rewrite that this is the last command to process when the rule returns true. So you would either need to do this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Or the following... but he was using a passthru flag which means that he is implying there are other things that could be processed prior to the last rule (eg. might be rewrite_base or alias), but that's not actually the case with his .htaccess file since it's a little bare. So this code would work similar to the code above but not exactly the same. They can't be used together though, and really there would be no need to:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php?url=$1
</IfModule>
The difference is the in the way it's processed. On the first .htaccess example you're passing any file to index.php regardless of whether it exists or not. You can [accidentally] rewrite a path that has a real file so that the real file is never accessed using this method. An example might be you have a file called site.css that can't be accessed because it's being redirected back to index.php.
On the second ruleset he's at least checking to see if the server doesn't have a file or a directory by the name being requested, then they're forwarding it to index.php as a $_GET variable (which seems a little pointless).
The way I typically write these (since I know mod_rewrite is already loaded in the config) is to to this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mydomain.com
RewriteRule (.*) http://www.mydomain.com/$1 [R=301,L]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule .* index.php
In my PHP code I pull the $_SERVER['REQUEST_URI'] and match it against a list of URIs from the database. If there's a match then I know it's a real page (or at least a record existed at some point in time). If there's not a match, then I explode the request_uri and force it through the database using a FULLTEXT search to see what potentially might match on the site.
Note: if you blindly trust the request_uri and query the database directly without cleaning it you run the risk of SQL injection. You do not want to be pwnd.
<?php
$intended_path = $_SERVER['REQUEST_URI'];
if(in_array($intended_path,$uris_from_database)){
//show the page.
} else {
$search_phrase = preg_replace('!/!',' ',$intended_path);
$search_phrase = mysqli_real_escape_string($search_phrase);
$sql = "SELECT * FROM pages WHERE MATCH (title,content) AGAINST ('$search_phrase');"
}
Sorry if this sounds a bit pedantic, but I've had experience managing a couple of million dollar (scratch) website builds that have had their hurdles with people not sticking to a standard convention (or at least the agreed upon team consensus).

How to implement URL pattern interpreter as used by Django and RoR in PHP

What's the best way to implement a URL interpreter / dispatcher, such as found in Django and RoR, in PHP?
It should be able to interpret a query string as follows:
/users/show/4 maps to
area = Users
action = show
Id = 4
/contents/list/20/10 maps to
area = Contents
action = list
Start = 20
Count = 10
/toggle/projects/10/active maps to
action = toggle
area = Projects
id = 10
field = active
Where the query string can be a specified GET / POST variable, or a string passed to the interpreter.
Edit: I'd prefer an implementation that does not use mod_rewrite.
Edit: This question is not about clean urls, but about interpreting a URL. Drupal uses mod_rewrite to redirect requests such as http://host/node/5 to http://host/?q=node/5. It then interprets the value of $_REQUEST['q']. I'm interested in the interpreting part.
If appropriate, you can use one that already exists in an MVC framework.
Check out projects such as -- in no particular order -- Zend Framework, CakePHP, Symfony, Code Ignitor, Kohana, Solar and Akelos.
have a look at the cakephp implementation as an example:
https://trac.cakephp.org/browser/trunk/cake/1.2.x.x/cake/dispatcher.php
https://trac.cakephp.org/browser/trunk/cake/1.2.x.x/cake/libs/router.php
You could also do something with mod_rewrite:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ $1 [L]
RewriteRule ^([a-z]{2})/(.*)$ $2?lang=$1 [QSA,L]
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
This would catch urls like /en/foo /de/foo and pass them to index.php with GET parameters 'lang' amd 'url'. Something similar can be done for 'projects', 'actions' etc
Why specifically would you prefer not to use mod_rewrite? RoR uses mod_rewrite. I'm not sure how Django does this, but mod_php defaults to mapping URLs to files, so unless you create a system that writes a separate PHPfile for every possible URL (a maintenance nightmare), you'll need to use mod_rewrite for clean URLs.
What you are describing in your question should actually be the URL mapper part. For that, you could use a PEAR package called Net_URL_Mapper. For some information on how to use that class, have a look at this unit test.
The way that I do this is very simple.
I use wordpress' .htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
What this .htaccess does is when something returns a 404, it sends the user to index.php.
In the above, /index.php is the "interpreter" for the URL.
In index.php, I have something along the lines of:
$req = $_SERVER['REQUEST_URI'];
$req = explode("/",$req);
The second line splits up the URL into sections based on "/". You can have
$area = $req['0'];
$action= $req['1'];
$id = $req['2'];
What I end up doing is:
function get_page($offset) {//offset is the chunk of URL we want to look at
$req = $_SERVER['REQUEST_URI'];
$req = explode("/",$req);
$page = $req[$offset];
return $page;
}
$area = get_page(0);
$action = get_page(1);
$id = get_page(2);
Hope this helps!
Just to second #Cheekysoft's suggestion, check out the Zend_Controller component of the Zend Framework. It is an implementation of the Front Controller pattern that can be used independently of the rest of the framework (assuming you would rather not use a complete MVC framework).
And obviously, CakePHP is the most similar to the RoR style.
I'm doing a PHP framework that does just what you are describing - taking what Django is doing, and bringing it to PHP, and here's how I'm solving this at the moment:
To get the nice and clean RESTful URLs that Django have (http://example.com/do/this/and/that/), you are unfortunately required to have mod_rewrite. But everything isn't as glum as it would seem, because you can achieve almost the same thing with a URI that contains the script's filename (http://example.com/index.php/do/this/and/that/). My mod_rewrite just forwards all calls to that format, so it's almost as usable as without the mod_rewrite trick.
To be truthful, I'm currently doing the latter method by GET (http://example.com/index.php?do/this/and/that/), and fixing stuff in case there are some genuine GET variables passed around. But my initial research says that using the direct slash after the filename should be even easier. You can dig it out with a certain $_SERVER superglobal index and doesn't require any Apache configuration. Can't remember the exact index off-hand, but you can trivially do a phpinfo() testpage to see how stuff look like under the hood.
Hope this helps.

Categories