0
votes

I'm new to CakePHP, though not new at all to MVC frameworks for web development. I'd normally go with Drupal when doing web sites that are not web apps but my employee feels that coding stuff from the ground up is far better than using pre built well tested and working solutions. Sigh.

Anyways, he agreed to at least let me use a framework, and I chose CakePHP because a) I've always wanted to learn it, and b) I love Rails so much I can't honestly go back to Zend once more :) Whatever, I decided to have some Cake so bear with me :)

I set up a whole lot of controllers and stuff implementing all the features of the site, and now I'd need to set up Drupal-like url aliases. Such an alias is something that lets you request http://www.example.com/this-be-me-page and display the same page that you'd have seen if you requested http://www.example.com/pages/42 for example. Or return the same as /article/301 when you type /blog/the-most-excellent-post-ever — I guess you got how it works.

I set up a database and a model such that I can query for the "alias" and retrieve the "internal url", then I'm stuck. It seemed that calling

$html = $this->requestAction($internal_url, array('return'));

would have returned the fully rendered HTML as if my user directly requested $internal_url but it's not the case. I only get the HTML for the action's view, without all the awesome layout stuff.

I'm going this database/controller way because I'd like site's admins to be able to edit the aliases via browser, not by editing some obscure routing directives or the .htacces. It's also much quicker to log in, create a page, set the alias and go out for lunch.

Now: how do I do it?

EDIT Mimicking the behaviour of app/webroot/index.php I wrote this action for my AliasController:

public function parse() {
    $alias = $this->request->params['url'];

    $record = $this->Alias->findByAlias($alias);
    $request = $record['Alias']['request'];

    $Dispatcher = new Dispatcher();
    $Dispatcher->dispatch(new CakeRequest($request), new CakeResponse(array('charset' => Configure::read('App.encoding'))));

    die;
}

Except for the name (it doesn't really parse anything, does it?) it works fine… at least it does what I wanted it to do. But I still feel dirty :) Does anybody have suggestions?

1
try using routes you may want something like thisapi55
I already have a "catch all" route that maps "/:url" to AliasController::parse, thus passing everything as a parameter. I think what I need is not feasible using only routes, I need to take the request url, look it up in the database, retrieve the "internal url" that corresponds to some other route, and dispatch it. I thought it was clear from the example I gave. Moreover, all the other routes work perfectly, so for example "/articles/1" does get caught by the "/articles/:id" route, not by the generic one.Morpheu5
oh i see, then you are looking for something like this and do some changes in the parse function to do the trick and accept id if the slug wasn't found or something like that... that way you can do it without calling again dispatcher and die at the endapi55
That seems more likely. This way, if a slug is found, I'll just have to build an appropriate CakeRoute and return it. Now, if you could please add this as an answer so I can accept it… :)Morpheu5
Sorry, wait: I forgot to mention I'm using CakePHP 2.0. Is that solution still appropriate or should I look at something else?Morpheu5

1 Answers

1
votes

Sorry for the late answer.

What you want to do is to re-do the parse method that CakeRoute uses. This way you can do as you want and parse the entry, and even use database to get the id of a slug like url. it is explain in more detail here you can do it like in the example, and add a if clause that if didn't find anything and (is numeric && !empty()) go as usual id...

Hope this works, i test it in 1.3 it SHOULD work in 2.0 since this is a feature NEW to 1.3 so you can create custom routes (i imagine lot of people had the same problem as you do) so i think it's going to work :)