Posts Tagged Admin Generator

Using Multiple Primary Keys in Admin Generator

Sometimes, the table we’re using force us to use multiple primary keys as shown in the schema below (config/schema.yml):

connection:            propel
defaultIdMethod:       native
package:               lib.model

classes:
  State:
    tableName:         state
    columns:
      id:              { type: varchar, size: 2, primaryKey: true }
      country_id:      { type: varchar, size: 2, primaryKey: true }
      name:            { type: varchar, size: 50, index: true }
      created_at:

By default, the symfony Admin Generator will only support single primary key. Since symfony 1.2, which adds sfRoute class, using multiple primary keys is possible by a configuration modifications and adds a few lines of code.

So now, generate the admin module by issuing:

symfony propel:generate-admin frontend State

Look at the generated route in apps/frontend/config/routing.yml:

state:
  class: sfPropelRouteCollection
  options:
    model:                State
    module:               state
    prefix_path:          state
    column:               id
    with_wildcard_routes: true

Only a single primary key was generated, so the idea is concatenate the primary keys as a single column, separated by a dash (-) for example.

Modify the route:

state:
  class: sfPropelRouteCollection
  options:
    model:                State
    module:               state
    prefix_path:          state
    column:               countryandstate
    with_wildcard_routes: true
    model_methods:
      object:             doSelectForRoute
  requirements:           { countryandstate: '[a-zA-Z0-9\.\_\-\:]+' }

As seen in the modified route, we change the column name to countryandstate, add a model-methods for object configuration and change the countryandstate column requirements.

When an object converted as a route, the sfRoute class will check for toParams() method, so we can provide the value of countryandstate column by adding this code:

// lib/model/State.php
<?php

class State extends BaseState
{
  public function toParams()
  {
    return array('countryandstate' => implode('-', array($this->getCountryId(), $this->getId())));
  }
}

A model-methods for object configuration in the routing above, changes the method used by the sfRoute class to retrieve an object which match a route.

// lib/model/StatePeer.php
<?php

class StatePeer extends BaseStatePeer
{
  /**
   * Retrieve State object for routing.
   *
   * @param array $parameters  The route parameters
   * @return State
   */
  public static function doSelectForRoute($parameters)
  {
    if (!isset($parameters['countryandstate']))
    {
      return null;
    }

    $c = new Criteria();
    list($country, $state) = explode('-', $parameters['countryandstate']);
    $c->add(StatePeer::COUNTRY_ID, $country)
      ->add(StatePeer::ID, $state);

    return StatePeer::doSelectOne($c);
  }
}

The rest is, to customize the generated module and adjusting the form as you need.

, , ,

13 Comments