Creating urls with deep paths

Hi, I have a table with categories in a nested tree with a structure like this:

Animals

-Mammals

-Insects

-Fish

-Reptiles

Cars

-Sports Cars

–Ferraris

–Porshes

-4x4

–Landrovers

etc

Each category has many articles associated with it. I want to use URL rules so that I can create urls like

hxxp://website.com/cars/sports-cars/ferraris/an-article-about-ferraris.html

(I’m already converting the category and article names to their URL friendly equivelents, e.g. “Sports Cars” becomes “sports-cars”)

The problem is the current URL rule system doesn’t seem to support this kind of behaviour, I don’t want to create a new URL rule for each category as it’ll hog resources and be a nightmare to maintain - I’m dealing with hundreds of categories and sub categories.

Does anyone have any ideas on how best to approach this? Am I missing something obvious?

Many thanks

I think you need to post your rewrite rules and controller configuration to really get some solid answers.

It’s definitely do-able with one or two generic URL management rules.

Unfortunately I’m not at that stage yet, I’m planning out how it’s going to work and this seems to be a stumbling block. I’ll try to describe in more detail how it should work:

Say I have 2 models, one called "Category" and one called "Article".

The "Category" model has these attributes:

Category.id

Category.name

Category.stub

Category.parentId // Either null or the id of another category

and the following relations:

Category.children // has many -> Category

Category.parent // belongs to -> Category

Category.articles // has many -> Article

So the Category can either be a root node (it has no parent) or it can be a child of one of the other categories. (I’m aware a nested set is more efficient than this system, but I’m using this example for simplicity’s sake).

The "Article" model has these attributes:

Article.id

Article.name

Article.stub

Article.categoryId

As well as the relation:

Article.category // belongs to category

So the problem is, how do you efficiently link to a nested category or article?

Something like this sucks:




$this->createUrl("/article/show",array("category1" => $article->category->parent->parent->stub,"category2" =>  $article->category->parent->stub, "category3" =>  $article->category->stub,"stub" => $article->stub));



If instead we had a function on the Category model that returned that category’s path, like this:




class Category extends CActiveRecord

{

    public function getUrlPath()

    {

        if (is_object($this->parent))

        {

            $path = $this->parent->getUrlPath()."/".$this->stub;

        }

        else

        {

            $path = $this->stub;

        }

        return $path;

    }

    ...

}




This would be much nicer:




$this->createUrl("/article/show",array("categoryPath" => $article->category->getUrlPath(),"stub" => $article->stub));



In my controller I should be able to find the appropriate article and category by accessing $_GET[‘categoryPath’] and $_GET[‘stub’].

The problem is that URL manager doesn’t seem to handle this kind of behavior, instead it splits the category path into seperate $_GET variables. I believe this is happening because of the slashes in the URLs, if getUrlPath() returned category stubs seperated by “.” instead of “/” this would work, but URLs like this aren’t really what I was after:

hxxp://website.com/articles/cars.sports-cars.ferraris/an-article-about-ferraris.html

is not quite as good as

hxxp://website.com/cars/sports-cars/ferraris/an-article-about-ferraris.html

You can override CController::run method in ArticleController to handle this specific URL and than call needed action method.

Thanks, but how should the corresponding url rules be constructed? It seems if i have an url rule that matches anything then i’ll need to create URL rules for every other route before it, which becomes a bit of a pain.

I use default URL rules. For example, example.com/controller/action/many/other/params will work with default rules.