ORM - get_url()

Difficulty: Medium

Lately I have dabbled for a bit with Django. It’s quite impressive to have your administration rendered in an instant and apart from that it has some excellent features. Anyway, I’m back on Kohana now and got an idea from Django that might benefit you.

Since Kohana doesn’t employ reverse routing, e.g. you link to a controller method like html::anchor(array(’controller’=>’user’,'method’=>’login’)); which will generate a url based on the routes you have. So, if you have set a route ‘enter_website’=array(’controller’=>’user’,'method’=>’login’); linking to the controller and method like I just did will generate an url to ‘/enter_website’. It’s quite neat as it centralizes the linking to urls and you can change ‘enter_website’ anytime and all your links on your site change as well. Anyway, Kohana doesn’t come packed with this. It’s also quite complicated to implement and would mean revising the whole router.

However, what they did in Django is implement a get_absolute_url() method in the model. This makes for a very suitable way of url management as well. When using ORM, models represent a record in the database. Often, a record also represents a page on your website. For example, a record in the table articles represents an article on your website, internally that article is represented by the Article_Model. If you give this Article_Model a method get_url() you can have a single place that generates the url.

Let’s illustrate this with some code.

//models/article.php
class Article_Model extends ORM{
    public function get_url()
    {
        return 'article/view/'.$this->id.'/'.url::title($this->title);
    }
}

In your controller you pass a list of articles to the view

class Article_Controller extends Controller{
public function overview()
{
    $view=new View('articles');
    $view->articles=ORM::factory('article')->find_all();
    $view->render(true);
}
public function view($id,$title)
{
    //show article
}
}

Your view is where the magic happens

//views/articles.php
echo '<ul>';
foreach($articles as $article)
{
    echo '<li>'.html::anchor($article->get_url(),'Article: '.$article->title).'</li>';
}
echo '</ul>';

See, now we can change the get_url() method and as long as you’re consistent in applying get_url(), all urls will change along. Visit an url example.com/article/view/1/article-title for example.

//in your model
    public function get_url()
    {
        //the same but we leave out 'view'
        return 'article/'.$this->id.'/'.url::title($this->title);
    }

In your controller

public function _default($method,$arguments){
if(is_int($method))
{
    $this->view($method,$argument[0]); //I haven't tested the _default method in this example but theoretically it should work
}
else
{
    Event::run('system.404');
}
}

Now you can access example.com/article/1/article-title , so no mention of the ‘view’ method. And, all your urls will have adapted to this. I hope you find it useful.


One Response to “ORM - get_url()”

  1. Learning Kohana » Sitemap generation Says:

    [...] a serious PITA. Today I whipped up a small library for Kohana to aid in this. In part it uses the get_url() method I posted on [...]

Leave a Comment