Page 1 of 2

Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 2:08 pm
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?

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 2:48 pm
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.

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 6:14 pm
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.

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 6:31 pm
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?

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 6:35 pm
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.

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 6:51 pm
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.

Re: Clean URLs from an application design perspective

Posted: Fri Aug 01, 2008 8:34 pm
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.

Re: Clean URLs from an application design perspective

Posted: Sat Aug 02, 2008 6:12 pm
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.

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 7:57 am
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?

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 9:16 am
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.

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 11:01 am
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.

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 11:08 am
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

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 12:55 pm
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.

Re: Clean URLs from an application design perspective

Posted: Sun Aug 03, 2008 12:58 pm
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

Re: Clean URLs from an application design perspective

Posted: Mon Aug 04, 2008 12:11 am
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.