Url representation in php - php

I am used to representing embedded url information like this:
http://test.com/reports/statement.php?company=ABC&q=1
how would I do it like this instead?
http://test.com/reports/ABC/Q1

You need to use Apache mod_rewrite to achieve this.
If your server has it enabled, you could do something like this in .htaccess:
RewriteEngine on
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /statement.php?company=$1&q=$2 [L]

You can use $_SERVER['PATH_INFO'] to access anything in the URL docpath after the address of your script.
e.g.
http://test.com/reports/statement.php/ABC/Q1
...then in statement.php you would have the string "/ABC/Q1" in $_SERVER['PATH_INFO']
Of course, you'll need to setup your webserver to match the URL and target the correct script based on the HTTP request.

As stated by others, you have to use url rewriting.
Usually a php application that make use of it, it applies the pattern called Front Controller.
This means that almost every url is rewritten to point to a single file, where the $_SERVER['PATH_INFO'] is used to decide what to do, usually by matching with patterns you define for your actions, or return a 404 error if the url doesn't match any of the specified patterns.
This is called routing and every modern php framework has a component that helps doing this work.
A smart move would also be providing a tool to generate urls for your resources instead of handwriting them, so that if you change an url pattern you do not have to rewrite it everywhere.
If you need a complex routing system, check out the routing component of some major frameworks out there, e.g. Symfony2, Zend Framework 2, Auraphp.
For the simplest php router out there, check instead GluePHP. The codebase is tiny so you can make yourself an idea on how the stuff works, and even implement a small router that fits your needs if you want to.

Related

Dynamically create URLs

Something that is really confusing me is how sites have urls such as:
http://example.com/shop/
-and-
http://example.com/shop/product-category/games/
Originally, I thought you could simply just create a php file and use URL rewrite in the .htaccess. For example:
http://example.com/shop.php
http://example.com/shop.php/product-category.php/games.php (It just doesn't make sense).
Clearly, this is not the case as not only is it not efficient for more trailing slashes, but CMS's such as Wordpress automatically generate the content for the 'dynamic' URLs, and then redirect to a 301 page if the URL is not recognised.
I am wanting to implement this into my site, I'm just completely clueless on how I'd approach this. I am struggling to research deep into the topic due to myself being unaware what this system actually is. Obviously, I'm looking at this completely wrong, which is causing me to confuse myself.
If someone could explain to what this system is called, and how I can do it. I'd prefer not to get spoon fed code, I just need someone to explain it all too me.
EDIT: After some further researching, I have found a perfect example to make my question clearer. Notice this url:
https://gamurs.com/g/csgo/players
has the same url as:
https://gamurs.com/g/csgo
But shows different content, it's a completely new page, that is being 'dynamically' created.
Then more random URLs from the same site:
https://gamurs.com/articles/world-esports-association-announced
https://gamurs.com/coaches
Thanks,
Sutton
So certainly if you were to use a framework like Laravel, its a very easy way of having routing.
There is a "routes.php" file in every project that defines calls to a URL and responds with a controllers method. This will generally return a view.
It makes it as easy to create something like this as adding a line like this
Route::get('home', 'PagesController#home');
to your routes file and when you go to example.com/home it will fire the controller called 'PagesController' and run its home method. Within this method you could return a view that will be the page that you want to display.
This can be expanded in other ways.
You could have another route that is nearly the same but have another method for when someone sends post data to the same controller.
Route::post('home', 'PagesController#submittedhome');
So now you have another route that will take a post input to that page and fire a completely different method from the same controller. These kind of controls + many many more can allow you to achieve what you want really easily and is part of the core fundamentals of laravel.
Here is the Routing page on the laravel page that can illuminate you a little more.
There are many frameworks that use the term url rewriting but obviously not referring to .htaccess. Frequently it's called routing. WordPress does this by using page slugs.
In WordPress, .htacces sends requests for existing files and directories directly through, bypassing WP. Anything not matching as described above must be a "virtual" page. and is sent to index.php
The URI is then parsed in one way or another usually involving regular expressions. Each part of the URI path correlates to a "slug", these are then used to create a database query to generate the relevant content.
There's a lot more going on in terms of selecting specific templates for certain slug types.
A low tech approach to achieve the same outcome without requiring routing is to create a folder with the desired name, and have an index.php (or index.html) within it. Then when the url is called - the default is to open the index file within the folder, even if it is not specified in the URL.
therefore
http://example.com/shop.php/product-category.php/games/
would be the equivalent of calling
http://example.com/shop.php/product-category.php/games/index.php
Note that I am NOT advocating this (I think it would get messy very quickly and there are way more efficient solutions), nor am I suggesting that the given examples are doing it this way, but I wanted to post this because it is a viable method to producing url's without file names or indexes listed. Just not a very good one IMO.
If someone could explain to what this system is called
It's called RewriteEngine and it's part of apache mod_rewrite, other web-servers have different mods, but this the most popular.
RewriteEngine on
RewriteRule ^shop/$ shop.php [L]
RewriteRule ^shop/products/(.*?)/$ products.php?type=$1 [L]
The 1st example will display the content of shop.php when a user accesses www.site.com/shop/
The 2nd example will send games, as argument ($1), to products.php?type=$1, if a user access www.site.com/shop/products/games/
[L] - is called a flag (L|last):
The [L] flag causes mod_rewrite to stop processing the rule set. In
most contexts, this means that if the rule matches, no further rules
will be processed. This corresponds to the last command in Perl, or
the break command in C. Use this flag to indicate that the current
rule should be applied immediately without considering further rules.
^ is relative to web root (somesite.com/^)
$ represents the end of the string (somesite.com/^somedir/test/$ this part will not be processed)
Resources:
Learn more about mod_rewrite and rewrite Flags

RESTful web service using PHP

We have data in our database as book-id, title, year, price, author, category. We need to retrieve data from the database using php. We can retrieve data of a book with book-id=123 by giving the url: www.localhost/books/?book-id=123 through $_GET method. But my requirement is I want to see that information of book with book-id=123 when I give the url: www.localhost/books/123
I am using a Wamp server for this.
You will have to enable mod_rewrite for your Apache. After this you can use a rewrite rule like this:
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)$ /$1/?id=$2
in your .htaccess File. This rule would internally redirect books/123 to books/?id=123.
See also: http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
There are two approaches here.
The wrong approach:
One could be to use your webserver to provide the URL rewrite rules (like the other answer says for Apache Web Server). As the other answer suggests. But that is not the right thing to do for application portability because your application depends on your web server type to route URLs.
The right approach:
The right approach is to do application level routing and keep the routing overhead as minimum to the web server as possible. Just direct your web server to point to one entry point of your PHP application (like one index.php). It would mean a regex matching for the incoming URL paths. I would suggest using an existing framework which provides routing capabilities like Laravel to prevent any missing corner cases in regex.
For e.g, if you really want to implement yourself, what you could do is follow the following steps:
$booksRoute = /^(\/)?books(\/)?[0-9]+(\/)?$/;
route($booksRoute, function() {
// process in the closure function
});

passing GET parameters that look like URI directories

I've seen a lot of URIs that look something like this:
www.fakesite.net/stories/1234/man_invents_fire
and I was wondering if the /1234/man_invents_fire part of the URI are actually directories or if they are GET parameters (or something else). I've noticed that a lot of times the /man_invents_fire segment is unnecessary (can be removed with no consequences), which led me to believe that the /1234/ is the id number for the story in a database table (or something along those lines).
If those segments of the URI are GET parameters, is there an easy way of achieving this?
If they aren't, what is being done?
(also, I am aware that CodeIgnitor gives this kind of functionality, but I was curious to find out if it could be easily achieved without CodeIgnitor. I am, however, generally PHP, if that is relevant to an answer)
Thanks
Easiest thing to do is route everything into a main index.php file and figure out your routing from there by running $pieces = explode("/", $_SERVER['REQUEST_URI']);
After installing/enabling mod_rewrite, make sure allow override is not set to false in your apache config (to allow .htaccess to be read), then throw this in your docroot's .htaccess file.
<ifModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-s #Make sure the file doesn't actually exist (needed for not re-routing things like /images/header.jpg)
RewriteRule . /index.php [L,QSA] #re-route everything into index.php
</IfModule>
That is called url rewriting, google for it, you will find a lot of information about that.
Implementing this in PHP is typically done via an .htaccess file and using apache's mod_rewrite module.
They make the url like that so that people can easily bookmark it, and it can return safely in the search.
Depends on what language you're using to decode it. In this case, it appears "stories" is the main script, and "1234" is the id, and "man_invent_fires" is the title.
If you're using php, you can use the $_SERVER['PHP_SELF'] or $_SERVER['REQUEST_URI'] variable to decode it.
If you're planning to make a website like that, certain safety must be kept in mind. Look them up in google, but key one to look out for is sql injectors.
Just like permalinks in WordPress, this is done typically done via Apache's mod_rewrite (or an equivalent thereof if not using Apache); however, you can also use a 404 error page handler to achieve the same result (but this is not usually recommended).
Typically, all page requests are redirected to a gateway that parses the requested URI to determine if it fits the specified pattern (in your case likely to be /{category}/{article_id}/{article_title}). From there, the gateway can typically use just the article_id to retrieve the appropriate content.
Depending on the system, category and article_title can usually be thrown away/ignored and are typically for SEO value; however, in some cases category might be used to augment article_id in some way (e.g.: to determine what DB table to query, etc).
MVC's, like Zend, also use a similar technique to determine which controller and method therein to execute. An example format for this type of use is /{module}/{controller}/{method}; however, this is highly customizable.
Well, you are kind of right in assuming that the 1234 and main_invents_fire are parameters. They are not truly GET parameters in the sense that the HTTP protocol describes them but they accomplish the same task, while keeping the URL "friendly". The technique is called URL rewriting and the web is full of info on this these days..
Here's an article about friendly URLs in PHP but I'm sure googling for the topic will render more useful results.
As some background information in addition to the answers before me, a URL is just that - a 'Uniform Resource Locator'. Although in the old days, it often used to map 1:1 to a file/directory structure, all that is required in the HTTP spec is to identify a certain resource. Basically that means that, given a certain string, it should indicate a certain 'resource' on the server. In practice, in a HTTP environment this is usually implemented with a rewriting mechanism such as mod_rewrite. RFC's such as this one: http://www.ietf.org/rfc/rfc1738.txt give a nice, albeit abstract, overview. The concepts only come to life after designing and implementing some non-obvious uses, though.
If you are using Symfony, then you can use the routing feature to do this.

Creating a RESTful API and website with PHP

I've got a PHP application I wrote earlier that I'd like to add a RESTful API to. I'd also like to expand the site to behave more like a Rails application in terms of the URLs you call to get the items in the system.
Is there any way to call items in PHP in a Railsy way without creating all kinds of folders and index pages? How can I call information in PHP without using a GET query tag?
If you have some form of mod_rewrite going you can do this quite easily with a .htaccess file.
If you have something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
It will check that the file you are trying to access doesn't exist already. (Say you had a file hello.html that you still needed people to access via http://yoursite.com/hello.html)
Then if the file doesn't already exist it will load your index.php file with the rest of the URL stored in the url variable.
This means you can call something like this http://yoursite.com/pages/edit/24 and it will load index.php with /pages/edit/24 inside the url variable.
That should get you started and you won't need all kinds of folders and index pages, just mod_rewrite, .htaccess file and an index.php that will be used to load whatever you need.
You also might consider to use one of the PHP frameworks with built-in REST support, for example CakePHP.
Quick note in respopnse to Pascal MARTIN: Zend_Rest_Server has absolutely nothing to do with REST. They just do RPC with slightly nicer URLs and call it REST so that it's more trendy.
If you want to do REST, you'll need to do a bit more work yourself as I have not found a good REST library for PHP yet. So inspect $_SERVER['REQUEST_METHOD'] to decide what to do with the called resource, etcetera.
Easiest way would probably using a framework that provides you with REST-oriented functionnalities. I know Zend Framework does that, with the class Zend_Rest_Server, that allows easy creation of a REST server.
I suppose many other frameworks do just the same.
But, if you already have an application that doesn't use a framework (or that is based on a Framework that doesn't embed that kind of class), a couple of URLrEwriting rules would do just fine ; you'd just have a bit more work to map URLS/parameters to classes/methods :-(
The design pattern you are looking for is called a front controller.
In its simplest form you use mod_rewrite to pass the incoming requests and pass it to a single php script. The url is then parsed with regular expressions and mapped to different response actions. However mapping an existing application may require extensive rewriting.
If you want to play around with this concept I recommend the Silex microframework.

php Zend / MVC without mod_rewrite

I've seen it mentioned in many blogs around the net, but I believe it shoud be discussed here.
What can we do when we have an MVC framework (I am interested in ZEND) in PHP but our host does not provide mod_rewrite?
Are there any "short-cuts"? Can we transfer control in any way (so that a mapping may occur between pages)? Any ideas?
Thank you :-)
Zend framework should work without mod_rewrite. If you can live with your URL:s looking more like "/path/to/app/index.php/controller/action". If you had mod_rewrite you could do away with the "index.php" bit, but it should work with too.
It's all a matter of setting up the routes to accept the index.php part.
OK my verdict :-): I have used successfully zend without mod_rewrite and it's as you've all said site/index.php/controller/action. I knew that before posting this. I've also found out around the net a technique that "pushes" 404 pages to index.php therefore what is not a resource (eg. CSS, image, etc) get there, with one exception: POST values.
So I decided that the next time an application has to be made in the specific server, to ask politely for mod_rewrite. If the administrator can not provide it, talk with my boss or if it is for me, switch provider.
Generally, it is a shame sometimes that the PHP market is so much fragmented (php4, php5, php6, mod_rewrite, mod_auth, mod_whatever), but this is another story...
mod_rewrite is almost essential in today's hosting environment..but unfortunately not everyone got the message.
Lots of the large php programs (I'm thinking magento, but most can cope) have a pretty-url fall back mode for when mod_rewrite isn't available.
URLs end up looking like www.site.com/index.php?load-this-page
They must be running some magic to grab the variable name from the $_GET variable and using it as the selector for what module/feature to execute.
In a related note, I've seen lots of messed up URLs in the new facebook site where it's using the #. So links look like www.new.facebook.com/home.php#/inbox/ Clearly we're not meant to see that but it suggests that they're probably parsing the $_SERVER['REQUEST_URI'] variable.
If you can find a non-mod_rewrite way to redirect all requests to index.php (or wherever your init script is), you can, as mentioned above, use 'REQUEST_URI' to grab the portion of the address after the domain and then parse it as you like and make the request do what you want it to. This is how Wordpress does it (granted, with mod_rewrite). As long as you can redirect requests to your index page while retaining the same URI, you can do what you need to to process the request.
Drupal's rewrite rules translate
http://example.com/path/goes/here
into
http://example.com/index.php?q=path/goes/here
...and has logic to decide which flavor of URLs to generate. If you can live with ugly URLs, this would let you keep all the logic of a single front controller in place w/o relying on URL rewriting.

Categories