Search code examples
doctrineinternationalizationforeign-key-relationshipslug

Doctrine Sluggable Behavior for Foreign Relations


I have a database design case which I am curios whether Doctrine ORM supports it out-of-box.


Product:
  columns:
    id: {type: integer, primary: true, autoincrement: true }
    type_id: { type: integer, notnull: true }
    brand_id: { type: integer, notnull: true }
  relations:
    ProductType:
      class: ProductType
      local: type_id
      foreign: id
    Brand:
      class: Brand
      local: brand_id
      foreign: id

ProductType:
  actAs:
    I18n:
    fields: { name }
  columns:
    id: {type: integer, primary: true, autoincrement: true }
    name: { type: string(255), notnull: true }

Brand:
  actAs:
    I18n:
      fields: { name }
  columns:
    id: {type: integer, primary: true, autoincrement: true }
    name: { type: string(255), notnull: true }


I want to slugify Products table, ie. products will be reached via their slugs. However, as you see both brand and productype tables has i18n behaviour. And moreover, product doesnt have a name. A product's slug will be: "Brand.name - ProductType.name", and vary with the language served.

For this scenario, is there anyway I can use Sluggable behaviour of Doctrine to sluggify my products automatically. Or do I have to manage it manually?

By the way my environment configuration is:
Doctrine Version: 1.2
Symfony: 1.4.1

Thanks


Solution

  • My understanding is that you need to have the slug in both Product Type and Brand models. You can leave the Product definition as it is. Anyway, I'm assuming from your question that there is only one product for every brand+type (even if it doesn't have to much sense). So ProductType and Brand will be defined like this:

    schema.yml
    ----------
    
    ProductType:
      actAs:
        I18n:
        fields: { name }
        actAs:
          Sluggable: { fields: [name], uniqueBy: [lang], canUpdate: true }
      columns:
        ...
    

    Then you have to configure your Product route to use the slugs. And after that you will need to configure the action to check what you are getting from the route.

    For example, this could be your route for Products:

    routing.yml
    -----------
    
    product:
      url:   /:sf_culture/product/:brand_slug/:type_slug
      param: { module: product, action: view }
      requirements:
        sf_culture: (?:en|fr)
        sf_method:  get
    

    Then in the action you will call to your own findOneBySlugs($brand_slug, $type_slug) method:

    product/actions/actions.class.php
    ---------------------------------
    
    public function executeView(sfWebRequest $request)
    {
      $product = Doctrine::getTable('Product')
        ->findOneBySlugs(
                         $request->getParameter('brand_slug'),
                         $request->getParameter('type_slug')
                        );
    
      $this->forward404Unless($product);
    }