lunes, 24 de octubre de 2011

sfDependentSelectPlugin en relaciones Muchos a Muchos M:N

Bien.. imaginemos que tenemos 2 tablas que se relacionan de M:N es decir, exite una tabla intermedia con las llaves primarias de las 2 tablas principales. en mi caso: centro y motivo_egreso y la tabla intermedia motivo_egreso_centro.


para usar sfDependentSelectPlugin y mostrar en mi caso, motivo de egreso y que se listen los centros asociados a través de una tabla intermedia , la única forma que conseguí de hacerlo es la siguiente: en lib/form/Doctrine/TuClaseForm.class.php
     public function configure()
     {
     ................. 
     ................. 
     ................. 
      $this->widgetSchema['motivo_egreso_id'] = new sfWidgetFormDoctrineChoice(array(
            'model'     => 'MotivoEgreso',
            'add_empty' => '<- Seleccione ->',
            'method' => 'getDescripcion',
            'label' => 'Motivo de Egreso :',
        ));

        $this->validatorSchema['motivo_egreso_id'] = new sfValidatorDoctrineChoice(array(
            'model' => 'MotivoEgreso',
            'column' => 'id',
            'required' => true
        ),array('required'=>'Campo requerido'));

        $this->widgetSchema['centro_id_egreso'] = new sfWidgetFormArrayDependentSelect(array(
            'callable' => array('CentroTable', 'getCentrosByMotivoEgreso'),
            'depends' => 'motivo_egreso_id',
            'add_empty' => '<- Seleccione ->',
        ));

         $this->validatorSchema['centro_id_egreso'] = new sfValidatorChoice(array(
            'choices' => CentroTable::getCentrosByMotivoEgreso(),
            'required' => true
        ),array('required'=>'Campo requerido'));
     ................. 
     ................. 
     ................. 
Luego defines el metodo getCentrosByMotivoEgreso() en mi caso en lib/model/doctrine/CentroTable.class.php
class CentroTable extends Doctrine_Table
{
    public static function getInstance()
    {
        return Doctrine_Core::getTable('Centro');
    }
     ................. 
     ................. 
     .................    
    
    public static function getCentrosByMotivoEgreso()
    {
        $motivos = Doctrine_Core::getTable('MotivoEgreso')
                    ->createQuery('m')
                    ->innerJoin('m.MotivoEgresoCentro mc')
                    ->innerJoin('mc.Centro c')
                    ->orderBy('m.id,c.id asc' )
                    ->execute();
        $arr = array();$arr_centro=array();
        foreach($motivos as $motivo){
            foreach($motivo->getCentro() as $centro)
                $arr_centro = $arr_centro + array($centro->getId() => $centro->getDescripcion());    
            $arr = $arr + array($motivo->getId()=>$arr_centro);
            $arr_centro=array();
        }
        return $arr;
    }
     ................. 
     ................. 
     ................. 
}
Bien, la idea que conseguí la obtuve de http://www.symfony-project.org/plugins/sfDependentSelectPlugin, en la seccion de "Using arrays only" decidí crear un array con la consulta que necesitaba para realizar los combos dependientes... repito es la única forma que conseguí de hacer eso, quizás exista una mejor manera, espero sus comentarios! Pd: el widget que deben usar en el form es sfWidgetFormArrayDependentSelect y ahi si utilizas el arreglo generado! Listo a probar...