propel

Projeto QuemLiga

Eu (Pedro Casado) e meu amigo Bernardo Alves criamos um projeto chamado Quem Liga feito com symfony 1.4 e propel 1.4.

O projeto ‘Quem liga’ é um banco de dados que armazena telefones de pessoas/empresas que incomodam nosso dia-a-dia oferecendo produtos, cobrando contas, se passando por outras pessoas, etc.

Se você recebeu uma ligação, uma mensagem ou é apenas um número desconhecido e quer saber mais sobre ele, você não é o único. Faça uma busca pelo telefone em nossa base e veja o comentário de outras pessoas.

Se ainda não houver comentários, seja o primeiro e deixe seu recado.

Estamos abertos para sugestões e comentários.

www.quemliga.com.br

php
propel
symfony

Comments (0)

Permalink

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

ajax
doctrine
form
php
plugins
propel

Comments (3)

Permalink

Tratando múltiplos telefones com embedded forms no admin generator

No meu post anterior, comentei sobre uma tabela (imovel) que possui diversos telefones (1-N). Nesse post vou tentar explicar como fiz o formulário de edição para tratar os N telefones dos imoveis.

O jeito que fiz vai ficar como a imagem abaixo. Vou deixar sempre 3 campos em branco para adicionar novos telefones. Para remover um telefone, basta deixa-lo em branco (em breve eu crio um botão com ajax para remover).

Vamos começar editando o lib/form/ImovelForm.class.php

class ImovelForm extends BaseImovelForm
{
  public function configure()
  {
      $todoWrapperForm = new sfForm();
      if ($this->getObject()->countTelefoneImovels() > 0) {
          foreach ($this->getObject()->getTelefoneImovels() as $telefone){
             $todoWrapperForm->embedForm(‘tel_’.$telefone->getId(), new TelefoneImovelForm($telefone));
          }
      }
    // adiciona os 3 forms em branco
    $todoWrapperForm->embedForm(‘tel_A’, new TelefoneImovelForm());
    $todoWrapperForm->embedForm(‘tel_B’, new TelefoneImovelForm());
    $todoWrapperForm->embedForm(‘tel_C’, new TelefoneImovelForm());

    $this->embedForm(‘tels’, $todoWrapperForm);

    $this->validatorSchema->setOption(‘filter_extra_fields’, false);
    $this->validatorSchema->setOption(‘allow_extra_fields’, true);

  }

  public function bind(array $taintedValues = null, array $taintedFiles = null) {
    foreach($this->embeddedForms[‘tels’]->getEmbeddedForms() as $key=>$telForm)
    {
       if ($taintedValues[‘tels’][$key][‘telefone’] == "")
       {
          unset($this->embeddedForms[‘tels’]->embeddedForms[$key], $taintedValues[‘tels’][$key]);
          $telForm->getObject()->delete();
       }
    }
    parent::bind($taintedValues, $taintedFiles);
  }

  // http://trac.symfony-project.org/ticket/5842
  public function saveEmbeddedForms($con = null, $forms = null, $taintedValues = null, $taintedFiles = null)
  {
    //atualiza o imovel_id da telefone_imovel depois de ter o imovel salvo
    //http://www.thatsquality.com/articles/embedding-child-forms-with-sfformpropel-a-practical-example
    foreach($this->embeddedForms[‘tels’]->getEmbeddedForms() as $telForm)
    {
       if (!$telForm->getObject()->getImovelId())
       {
         $telForm->getObject()->setImovelId($this->getObject()->getId());
       }
    }

    if (is_null($con))
    {
      $con = $this->getConnection();
    }

    if (is_null($forms))
    {
      $forms = $this->embeddedForms;
    }

    if (is_null($taintedValues))
   {
      $taintedValues = $this->taintedValues;
   }

   if (is_null($taintedFiles))
   {
      $taintedFiles = $this->taintedFiles;
   }

   foreach ($forms as $key => $form)
   {
       // é esse trecho que corrige o problema
       if ($form instanceof sfFormPropel)
       {
          $form->bindAndSave($taintedValues[$key], $taintedFiles);
       } else {
          $this->saveEmbeddedForms($con, $form->getEmbeddedForms(), $taintedValues[$key], $taintedFiles);
       }
   }
 }
}
 

Agora vamos criar um partial para mostrar os telefones no formulário. Crie o arquivo apps/backend/imovel/templates/_tels.php


<div id="embed_tels">
<?php foreach ($form->getEmbeddedForms() as $key => $itemForm) {
             if (substr($key , 0 , 8) == ‘tels’): ?>
                 <div class="sf_admin_form_row sf_admin_text sf_admin_form_field_telefone<?php echo preg_replace("/[^0-9]/", ‘’, $key); //only number ?>">
                    <div>
                       <?php echo $form[$key]; ?>
                    </div>
                 </div>
             <?php endif ?>
<?php } ?>
</div>
 

Depois de ter criado o partial, basta adiciona-lo ao apps/backend/imovel/config/generator.yml


edit:
  display: [_tels, campo1, campo2]
 

É isso.. tive como referência diversos sites, mas principalmente o blog that’s quality.

http://www.thatsquality.com/search?query=embedded

embedded form
form
php
propel

Comments (0)

Permalink