Selectbox para escolher cidade de acordo com o estado utilizando widgets e symfony 1.4 (Propel/Doctrine)

Nesse post vou explicar como fazer um selectbox que só mostra as cidades referentes ao respectivo estado selecionado anteriormente.

stado_cidade_sfDependentPlugin1.jpg

Vamos considerar a seguinte modelagem (config/schema.yml):


propel:
  estado:
    id:
    uf:   varchar(2)
    nome: varchar(60)

  cidade:
    id:
    nome:       varchar(40)
    estado_id:  { type: integer, foreignTable: estado, foreignReference: id, onDelete: cascade }
    capital:    varchar(1)
    created_at:
    updated_at:

  usuario:
    id:
    nome:        varchar(100)
    cidade_id:  { type: integer, foreignTable: cidade, foreignReference: id, onDelete: cascade }
 

Para preencher as tabelas estado e cidade, utilizei o seguinte SQL com dados do Brasil. CARGA_CIDADES_E_ESTADOS_BRASIL.zip

O próximo passo é instalar o plugin sfDependentSelectPlugin em nosso projeto. Baixe o arquivo sfDependentSelectPlugin-0.1.5.tgz e descompacte na pasta plugins/ de seu projeto. Eu renomeei a pasta de plugins/sfDependentSelectPlugin-0.1.5/ para plugins/sfDependentSelectPlugin/.

Habilite o plugin no seu projeto (config/ProjectConfiguration.class.php)

$this->enablePlugins(…, ‘sfDependentSelectPlugin’);

Limpe o cache do seu projeto:
$ php symfony cc

Publique o javascript do plugin com o comando:
$ php symfony plugin:publish-assets

Crie o CRUD para o usuário:
$ php symfony propel:generate-module frontend usuario Usuario

Agora vamos alterar o form do usuário: lib/form/UsuarioForm.class.php:
class UsuarioForm extends BaseUsuarioForm
{
  public function configure()
  {
    $this->widgetSchema[‘estado_id’] = new sfWidgetFormPropelChoice(array(
            ‘model’     => ‘Estado’,
            ‘add_empty’ => true
     ));

    $this->widgetSchema[‘cidade_id’] = new sfWidgetFormPropelDependentSelect (array(
            ‘model’     => ‘Cidade’,
            ‘depends’   => ‘Estado’,
            ‘add_empty’ => ‘Selecione a cidade’
    ));

    $this->validatorSchema[‘estado_id’] = new sfValidatorPropelChoice(array(
        ‘model’ => ‘Estado’,
    ));

    $this->validatorSchema[‘cidade_id’] = new sfValidatorPropelChoice(array(
        ‘model’ => ‘Cidade’,
    ));
  }
}

Vale lembrar que você pode utilizar o sfWidgetFormDoctrineDependentSelect ao invés do sfWidgetFormPropelDependentSelect.

Agora vamos alterar o template para receber o widget do estado também (\apps\APLICACAO\modules\usuario\templates\_form.php)


      <tr>
        <th><?php echo $form[‘estado_id’]->renderLabel() ?></th>
        <td>
          <?php echo $form[‘estado_id’]->renderError() ?>
          <?php echo $form[‘estado_id’] ?>
        </td>
      </tr>
      <tr>
        <th><?php echo $form[‘cidade_id’]->renderLabel() ?></th>
        <td>
          <?php echo $form[‘cidade_id’]->renderError() ?>
          <?php echo $form[‘cidade_id’] ?>
        </td>
      </tr>

Pronto! Acesse a página do módulo e veja o select da cidade dependente do select do estado.

Esse plugin faz um pouco mais do que isso como dependência infinita, utilização de ajax, etc.. Para ver a documentação completa acesse: http://www.symfony-project.org/plugins/sfDependentSelectPlugin