views:

46

answers:

1

Hi. I have this routing.yml:

post:
  class:   sfDoctrineRouteCollection
  options: { model: BlogPost }

I need this url: /company/24/mycompany/blog/post/13.

How how I can pass to my route 2 models to generate following route:

//Test route example
post_show:
  url: /company/:id/:title_slug/blog/post/:post_id
  param:   { module: company, action: show }
  class:   sfDoctrineRoute
  options: { model: MyCompany }

How I can describe second model here, to get attributes to the URL? Is it possible?

Many thanks.

+1  A: 

I've done it before, with a custom route class, a bit like this:

<?php

class sfDoctrineMultiRoot extends sfRequestRoute {

  public function matchesUrl($url, $context = array()) {

    if (false === $parameters = parent::matchesUrl($url, $context)) {
      return false;
    }
    $company = Doctrine_Core::getTable('Company')
            ->find($parameters['company_id']);

    if (!$company) {
      return false;
    }

    $blog = Doctrine_Core::getTable('Blog')
            ->find($parameters['blog_id']);

    if (!$blog) {
      return false;
    }

    $this->company = $company;
    $this->blog = $blog;

    return $parameters;
  }

  public function getCompany() {
    return $this->company;
  }

  public function getBlog() {
    return $this->blog;
  }


  public function generate($params, $context = array(), $absolute = false)
  {

    foreach ($params as $key=>$param) {
      if (method_exists($param, 'getRawValue')) {
        $params[$key] = $param->getRawValue();
      }
    }

    if (isset($params['company']) && $params['company'] instanceof Company) {
      $params['company_id'] = $params['company']->getId();
    }
    unset($params['company']);

    if (isset($params['blog']) && $params['blog'] instanceof Blog) {
      $params['blog_id'] = $params['blog']->getId();
      unset($params['blog']);
    }
    unset($params['blog']);

    return parent::generate($params, $context, $absolute);
  }

}

You have to use something like this in routing.yml:

test:
  url: /company/:company_id//blog/:blog_id
  class: sfDoctrineMultiRoot
  param:   { module: company, action: show }

You can generate urls via url_for and link_to like this:

url_for('test', array('blog'=>BlogObject, 'company'=>'CompanyObject'));

or

url_for('test', array('blog_id'=>1, 'company_id'=>2));

And to retrieve the objects in your action you can call:

$this->getRoute()->getBlog();

or

$this->getRoute()->getCompany();
benlumley
Thanks, but where I need to put this new route class?And how I tell to symfony to use it? Thanks.
Marat_Galiev
Doesn't really matter where you put it - symfony's auto loader will find it. I'd recommend making a folder in your project's lib folder called "route" and putting it in there (file called sfDoctrineMultiRoot.class.php ). You may need to clear your cache after adding the file.
benlumley
This is neither generic nor extensible. I support the idea of a multi-object doctrine route, but it should act similarly to sfDoctrineRoute, with the ability to specify models and methods.
jeremy
Whilst I agree with jeremy above - I happened to have the code already, so posted it to be helpful. It could be tidied up to be generic etc, maybe one day I will, but sometimes it just needs to be enough to work. And the day I wrote this was one of these days. Besides, I believe it is better than jeremy's solution, which so far is "start it from scratch". /rant.
benlumley