Search code examples
phpsymfony1propel

How to create route with different modules with same name?


I have 2 different models: category and page. My schema.yml:

propel:
  wiki_category:
    id:           ~
    address:      { type: varchar(255) }
    name:         { type: varchar(255), required: true }
    text:         { type: longvarchar }

  wiki_page:
    id:           ~
    category_id:  { type: integer, foreignTable: wiki_category, foreignReference: id, required: true}
    address:      { type: varchar(255) }
    name:         { type: varchar(255), required: true }
    text:         { type: longvarchar, required: true }

My routing.yml:

category_show:
  url:     /:address.:sf_format
  class:   sfPropelRoute
  options: { model: WikiCategory, type: object }
  param:   { module: category, action: show, sf_format: html }
  requirements: { sf_method: get }
homepage:
  url:   /
  param: { module: category, action: index }
page_show:
  url:     /:address/:address
  class:   sfPropelRoute
  options: { model: WikiPage, type: object }
  param:   { module: page, action: show, sf_format: html }
  requirements: { sf_method: get }

I want to make a route like /:address(from category)/:address(from page)

Is there any way to do this?

The idea is to make a page of categories with links to pages from this category. By pressing link executes action show of page.


Solution

  • Since you have two field with the same name, Propel won't be abble to understand wich one (from /:address/:address) is the one to use to get a WikiPage object.

    The first easiest option is to rename one address inside your schema. Like address_page for wiki_page, so you will be able to have a route like this /:address/:address_page and Propel will know how to retrieve a WikiPage object

    But I will recommend you this second option.

    Do not use class sfPropelRoute to retrieve your object. Use sfRequestRoute instead. And then, you can give what ever name you want for parameter. Something more explicit like: /:address_category/:address_page:

    page_show:
      url:     /:address_category/:address_page
      class:   sfRequestRoute
      param:   { module: page, action: show, sf_format: html }
      requirements: { sf_method: get }
    

    Then, inside the action, you must retrieve the object manually:

    $wikiPage = WikiPageQuery::create()
      ->filterByAddress($request->getParameter('address_page'))
      ->leftJoin('WikiPage.WikiCategory')
      ->where('WikiCategory.address = ?', $request->getParameter('address_category'))
      ->findOne();
    

    Just to let you know what sfPropelRoute does (basically):

    • try to retrieve an object using request parameter & routing configuration
    • if it can't find the object redirect to 404

    In your case, you already retrieved object, you now just need to forward to 404 if it doesn't exist:

    $this->forward404Unless($wikiPage);