Clean URLs from an application design perspective

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Clean URLs from an application design perspective

Post by VirtuosiMedia »

I'm trying to figure out a best practice for content management system that would allow for really simple clean URLs. I have something in mind, but I'd like to know if there is something better out there or if my example has any potential security problems.

Basically, I would set up a table similar to the following:

Code: Select all

CREATE TABLE 'pages' (
  'pageId' int(10) NOT NULL auto_increment,
  'pageTitle' varchar(200) NOT NULL,
  'pageDescription' text NOT NULL,
  'pageKeywords' text NOT NULL,
  'pageCleanUrl' varchar(200) NOT NULL,
  'pageType' varchar(100) NOT NULL,
  PRIMARY KEY  ('pageId'),
  UNIQUE ('pageCleanUrl')
)
The 'pageCleanUrl' column would be whatever URL the administrator chooses as the clean URL. It could be changed manually or it could be derived from something like a blog or product title, with the potential of a category or directory being prepended. Allowable characters would be alphanumeric characters, a forward slash, a hyphen, an underscore, and nothing else.

A URL without any rewriting would look like:

http://www.site.com/index.php?p=blog/my ... -blog-post

With URL rewriting, it would look like:

http://www.site.com/blog/my-latest-blog-post

In this case, I would get the parameter, validate it, sanitize it, and then run a query for it. The resulting 'pageId' (which would be used as a foreign index in multiple tables) would then act as a direction for the controller for all of the various pieces of page content, telling the page which parts to load.

Some of the advantages would be that the rewrite rule would be fairly simple and I could easily edit metadata or apply tags for any page on my site. Even without rewriting, the URL is at least somewhat readable. The main disadvantage I wonder about is security. If I check to make sure that only alphanumeric characters, a forward slash, hyphen, and underscore are the only characters used and if I bind the input as a parameter using PDO, will I have any security problems? Are there any performance or other problems to this approach? Does anyone have or can they point to better practices?
User avatar
ghurtado
Forum Contributor
Posts: 334
Joined: Wed Jul 23, 2008 12:19 pm

Re: Clean URLs from an application design perspective

Post by ghurtado »

Seems to me that your approach is how most people go about it, I have seen this implemented in a couple of ways, but at the end it really comes down to doing some sort of lookup of the clean URL in a database table. So in that regards, I think you are headed in the right direction.
VirtuosiMedia wrote:The main disadvantage I wonder about is security.
This is no more nor less secure than index.php?id=whatever, since in both cases (the clean and the "dirty" URL) the user provided parameter can end up in the middle of your SQL query. I assume you refer to SQL injection when you are concerned with security; the best way to avoid SQL injection in either case is to use prepared statements and named paremeters.
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

I really like how kyberfabrikken approaches clean urls in his Konstrukt framework (http://www.konstrukt.dk). Each section of the url corresponds to either a controller or a parameter. In the blog example, you could have /blog/posts/blost-post where blog = BlogController, posts = PostsController, and the post name is passed as a parameter to PostsController. It's a very flexible solution, and allows for reuseable controllers.

In his examples, the mappings from url section to controller are kept in a simple array:

Code: Select all

$map = array (
    'blog' => 'BlogController',
    'test' => 'TestController'
    );
I am looking at implementing this in the database, where a url section corresponds to a url_map table that gives me a controller to load and the content for it to use. It should end up being pretty slick, if all turns out well.
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: Clean URLs from an application design perspective

Post by VirtuosiMedia »

allspiritseve wrote:I really like how kyberfabrikken approaches clean urls in his Konstrukt framework (http://www.konstrukt.dk). Each section of the url corresponds to either a controller or a parameter. In the blog example, you could have /blog/posts/blost-post where blog = BlogController, posts = PostsController, and the post name is passed as a parameter to PostsController. It's a very flexible solution, and allows for reuseable controllers.

In his examples, the mappings from url section to controller are kept in a simple array:

Code: Select all

$map = array (
    'blog' => 'BlogController',
    'test' => 'TestController'
    );
I am looking at implementing this in the database, where a url section corresponds to a url_map table that gives me a controller to load and the content for it to use. It should end up being pretty slick, if all turns out well.
If you look at the way Joomla and maybe a few other CMS's out there handle URL's, I think it's similar to the way you describe. However, couldn't you do the same thing, with less parameters, by simply assigning controllers to the page ID in the database like the example I gave above? I'm not sure about what the best practice is, but to me it makes sense to keep the number of parameters minimal. What's the tradeoff?
User avatar
omniuni
Forum Regular
Posts: 738
Joined: Tue Jul 15, 2008 10:50 pm
Location: Carolina, USA

Re: Clean URLs from an application design perspective

Post by omniuni »

Probably flexibility. It's usually best to find a system that will suit you for a long while. That way, when you upgrade or change something, it doesn't just break. Even if you're not planning on updating anything, sometimes things break. It's best to do them as flexibly and simply as possible, so you can fix things easily if need-be.
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

VirtuosiMedia wrote:If you look at the way Joomla and maybe a few other CMS's out there handle URL's, I think it's similar to the way you describe. However, couldn't you do the same thing, with less parameters, by simply assigning controllers to the page ID in the database like the example I gave above? I'm not sure about what the best practice is, but to me it makes sense to keep the number of parameters minimal. What's the tradeoff?
I am not aware of any major CMS that does URLs like konstrukt.

At its simplest, konstrukt could have any URL you could write with the system you outlined. However, a page could have a URL like this:

Code: Select all

/page1/page2/page3/page4/page5/page6


This way, you could remove part of the url, and load the parent page. Remove some more, get the next page up. They could all be running from the same controller, being used in different contexts. This is waaay different from the usual /controller/method/parameter thing that usual MVC-based apps use. I would really recommend you take a closer look at the site, and go through the quick tutorials he has.
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: Clean URLs from an application design perspective

Post by VirtuosiMedia »

I took a look at the site and the examples, but I think I'm going to have to let it sink in for a little while and maybe reread it a couple times. I'm still new to a lot of this, so there is a lot that I don't understand yet. I kind of get some of the class structure, but I guess I'm having some difficulty understanding why each controller would have to be explicitly specified in the URL itself and how that offers a significant advantage over the other way. I'll look at it again, though.
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

VirtuosiMedia wrote:I guess I'm having some difficulty understanding why each controller would have to be explicitly specified in the URL itself and how that offers a significant advantage over the other way. I'll look at it again, though.
Well, each controller isn't explicitely specified.. since you have an array of URL-segment-to-controller mappings, you could have as many segments as you want using the same controller (ie a segment that corresponds to a page name could map to a PageController, which takes the page name and looks in the database for it). The segments could really map to anything though, its up to you if you want to override that functionality.

I wonder, though, what seems wrong to you about controllers being loaded from the URL? What would you prefer a URL to link to? I think typical MVC apps either have a url like /controller/method/param or map one URI to a controller with a router, but either way those controllers will have to handle a lot of information. Konstrukt takes out the standard HTTP stuff, and lets the controllers do their thing. It favors a lot of small controllers rather than a few large controllers.

If you have any questions, I know there's a Google group for the app, and Troels is pretty quick to respond.
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: Clean URLs from an application design perspective

Post by VirtuosiMedia »

allspiritseve wrote:I wonder, though, what seems wrong to you about controllers being loaded from the URL? What would you prefer a URL to link to? I think typical MVC apps either have a url like /controller/method/param or map one URI to a controller with a router, but either way those controllers will have to handle a lot of information. Konstrukt takes out the standard HTTP stuff, and lets the controllers do their thing. It favors a lot of small controllers rather than a few large controllers.
To be honest, some of my reservations may come from not completely understanding it. I think that perhaps some of my main reservations are (and they may prove unfounded) that I wanted to keep the URL as simple as possible because I view it as a part of the user interface. Not having each controller based on the URL seemed to be a separation of concerns and it also makes for a fairly simple rewrite rule because there is only one parameter to deal with. Using a single parameter allows for a small, single controller to handle every page, regardless of the directory depth of the URL. I also wanted to have the flexibility to be able to change any URL from an administrative backend, without having to write or rewrite any new code. Would I be able to do that with Konsrukt?
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

VirtuosiMedia wrote:I wanted to keep the URL as simple as possible because I view it as a part of the user interface.
I do as well.
VirtuosiMedia wrote: Not having each controller based on the URL seemed to be a separation of concerns and it also makes for a fairly simple rewrite rule because there is only one parameter to deal with. Using a single parameter allows for a small, single controller to handle every page, regardless of the directory depth of the URL. I also wanted to have the flexibility to be able to change any URL from an administrative backend, without having to write or rewrite any new code. Would I be able to do that with Konsrukt?
Not out of the box, but if you keep the URL to controller mappings in the database, you can edit anything. You wouldn't be able to modify a whole URL at once, but each individual "directory" could be changed. This is nice, because you can rename one directory, and every directory beneath it will have the new URL as well. In a standard routing scenario, you'd have to change every single URL that used that directory. It is also a usability thing, since you can remove a directory, and still get relevant content. /posts/blog-title/ gets a post, and /posts/ gets all posts. If you follow that style of URLs, you end up with small, readable URLs that ARE part of the user interface, and a user can manipulate to get the content they need.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Clean URLs from an application design perspective

Post by Christopher »

Almost every framework I know has a "router" that can map clean URLs to any kind of custom controller directory/class/method/params you want. And there is HordeRoute that is a stand-alone system that is very powerful. In most frameworks the "router" is tied into the Front Controller, so might be difficult to use in your code. I am not sure if the Konstrukt one is like this. I know the Skeleton one is separate from the Front Controller and only modifies a Request object.
(#10850)
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

allspiritseve wrote:Almost every framework I know has a "router" that can map clean URLs to any kind of custom controller directory/class/method/params you want. And there is HordeRoute that is a stand-alone system that is very powerful. In most frameworks the "router" is tied into the Front Controller, so might be difficult to use in your code. I am not sure if the Konstrukt one is like this. I know the Skeleton one is separate from the Front Controller and only modifies a Request object.
Well, there isn't much else to Konstrukt other than the routing. The idea is that it's distributed throughout many controllers, rather then located in a central "router". The "Working with Controllers" page gives a good summary. http://konstrukt.dk/working-with-controllers.html
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Clean URLs from an application design perspective

Post by Christopher »

allspiritseve wrote:Well, there isn't much else to Konstrukt other than the routing. The idea is that it's distributed throughout many controllers, rather then located in a central "router". The "Working with Controllers" page gives a good summary. http://konstrukt.dk/working-with-controllers.html
Yes. Actually, Konstrukt and Skeleton came out of the same design discussion that Troels and I were involved in. Konstrukt went the all-in-one Controller, whereas Skeleton went with the more standard (Struts like ;)) separate Front and Action controllers. Both were created before the current crop of frameworks like Cake and Zend were created.

You can use the Skeleton or Horde router with your own Controllers. They are not integrated into the framework's Controllers. You just need a basic Request object that wraps the request in a get()/set() interface.
(#10850)
User avatar
allspiritseve
DevNet Resident
Posts: 1174
Joined: Thu Mar 06, 2008 8:23 am
Location: Ann Arbor, MI (USA)

Re: Clean URLs from an application design perspective

Post by allspiritseve »

arborint wrote:Yes. Actually, Konstrukt and Skeleton came out of the same design discussion that Troels and I were involved in. Konstrukt went the all-in-one Controller, whereas Skeleton went with the more standard (Struts like ;)) separate Front and Action controllers. Both were created before the current crop of frameworks like Cake and Zend were created.
Ah. You probably know more about it than I do, then :D
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Clean URLs from an application design perspective

Post by Christopher »

allspiritseve wrote:Ah. You probably know more about it than I do, then :D
Konstrukt is cool and Troels is a very, very smart guy!

You may want to take a look at HordeRoute. It is very powerful. Maybe overkill for you guys.
(#10850)
Post Reply