Symfony Form Types
Criar um CRUD costuma ser bem simples. Mas, pode não ser quando temos muitos relacionamentos entre as entidades.
No caso do TikTok®,como criar um formulário que permita seleção de Funcionarios em HoraLancada? Ou até mesmo de Projeto em HoraLancada?
Mãos na massa
Agora que temos todos os mapeamentos bem definidos, precisamos de alguma tela que consiga cadastrar, listar, editar e persistir Projetos e HorasLancadas no banco de dados.
Todas essas funcionalidades precisarão estar bem separadas, certo? Por isso teremos um controller para cada entidade.
Projeto Controller
Criar e mostrar não é nenhuma novidade, precisamos das actions mostra(), formulario() e cria():
Listagem
Para listar todos, vamos precisar de uma rota nova, por exemplo:
/**
* @Route("/projeto/lista",methods="GET")
*/
public function lista()
E, dentro dela, precisamos pedir para o Doctrine todos os posts cadastrados no banco. Para realizar essas funcionalidades de busca o Symfony disponibiliza um repositório onde podemos buscar o que quisermos!
$repository = $this->getDoctrine()->getManager()->getRepository(Projeto::class);
Aqui estamos pedindo um repositório para a classe Projeto, já que é ela que queremos listar. Em seguida, basta devolver pra View todos os projetos do banco com o método findAll:
Remoção
Para remover, basta a gente pedir pro Doctrine remover e criar uma action que pegue o projeto em questão:
Depois de remover, voltamos para a listagem de projetos com o redirect =)
Edição
Ao editar um Projeto, precisamos conseguir mudar o nome dele e os funcionários associados a esse projeto. Isso significa que no nosso controller, temos que conseguir adicionar e remover funcionários da lista de funcionarios do projeto.
Além disso, precisamos garantir que sempre vai existir uma lista de Funcionarios nesse projeto, mesmo que vazia. Uma abordagem seria criar um array no construtor e atribuir a funcionários.
Mas, o próprio Doctrine tem uma classe para lidar com coleções de entidades relacionadas!
Criando os formulários
Além de criar métodos para adicionar e remover funcionários, precisaremos de uma tela para que o cliente realmente consiga selecionar esses funcionários. Para isso, precisaríamos buscar do banco de dados todos os funcionários e fazer uma listagem.
E não para por aqui, precisaríamos receber esses dados no controller. Chamar os métodos para atualizar os relacionamentos.
Tem bastante trabalho envolvido ao gerar formulários para entidades que possuem relacionamentos.
Problemas de manutenção
Caso a entidade mudasse e o relacionamento deixasse de existir ou mudasse o tipo do relacionamento, precisaríamos botar a mão em toda aquela estrutura necessária no controller e no front.
Gerenciando entidades com Form Type
Para resolver todos esses problemas relacionados a formulário, como renderizar na view, quais atributos devem aparecer no formulário ou não. Verificar validação e muito mais, o Symfony vem com um construtor de formulários!
Assim, só precisamos criar o formulario e utilizá-lo tanto no back-end quanto no front-end!
Para instalar o componente de formulários no Symfony, basta chamar o composer:
Vamos começar criando o formulário de edição na action mostra(). Para isso, basta pedir para o próprio controller o formBuilder:
Tendo o builder na mão, podemos dizer quais campos do projeto queremos no nosso form com o método add(). Qualquer campo que não passarmos pelo add, não será considerado no form.
Além disso, também podemos definir a action, com o método setAction() e até mesmo o método do formulário com o método setMethod()!
Depois de construir o formulário, precisamos renderiza-lo na view. Por isso mandamos para o método render o novo valor “form” =)
Renderizando o Form no Twig
Agora que temos toda a definição do form pronta no nosso Twig, podemos pedir para que o próprio Twig renderize todo o formulário com apenas 3 chamadas:
- FormStart() para abrir a tag form
- FormWidget() para processar todos os campos do formulário
- FormEnd() para fechar a tag form
Aplicando esses 3 no nosso Twig, temos:
Cada um dos métodos recebe como parâmetro justamente aquele form que criamos no controller! No nosso caso, demos o nome dele de form, mas poderia ser qualquer coisa =)
Se dermos uma olhada na nossa view renderizada, temos:
Além do campo nome, uma listagem onde podemos selecionar quantos funcionários quisermos, já puxando direto do banco!
Recebendo dados da view
Perfeito, conseguimos criar um formulário com o relacionamento. Mas, ainda falta puxar esses dados da view e mandar pro banco. Para isso, temos a action edita() que é destino nosso form.
A primeira coisa que precisamos fazer, é justamente montar o formulário:
Tendo o formulário pronto, basta pedirmos pra que ele mesmo olhe no request os dados que precisam ser settados, com o método handleRequest()!
Sim, depois dessa chamada, o próprio Symfony já populou toda a entidade Projeto com os dados que vieram do formulário =)
Validando
Além de receber todos os dados da view, podemos utilizar nosso form do back-end para validar a entidade com o método isValid():
Assim, se rolar algum erro não entramos no if e, por consequência, voltamos pra tela de edição com o mesmo projeto.
Agora que temos certeza que nossos dados estão validos, podemos atualizar os relacionamentos e mandar tudo pro banco de dados:
E pronto! Conseguimos editar nossa entidade Projeto e os relacionamentos dela com Funcionario, sem precisar buscar absolutamente nada do request diretamente.
Finalizando o projeto
Agora que conseguimos gerar todos os formulários no back-end, basta repetir o mesmo processo em todas as nossas actions.
Inclusive, agora o processo já é bem claro. Toda entidade que surgir no sistema, passará pela modelagem, a criação do controller com CRUD(criar, listar, atualizar e deletar), formType para gerenciar os dados e Twig para renderizar nossas Views =)
A parte mais importante em utilizar boas ferramentas, como o Symfony, o Doctrine, o Twig entre outras que comentamos nos últimos posts é justamente ter um bom processo pelo qual passamos toda nova funcionalidade no sistema.
Se toda feature é feita com ferramentas que garantem o desacoplamento e andam com as boas práticas, ganhamos a tendência de desenvolvê-la com o mesmo preceito!
Proximos passos
Agora que nosso sistema TikTok® está finalmente pronto, com injeção de dependências, template views, formTypes e tudo que a base do Symfony nos oferece de bom, no próximo post faremos o deploy dessa aplicação na Digital Ocean!
Um serviço bem famoso de locação de máquinas com acesso ssh que funciona muito bem e de forma bem parecida com todos os outros prestadores de serviço desse tipo como Amazon!
E ai, quer saber mais sobre FormTypes? Da uma olhada no post sobre validação com Event Listeners e Form Themes!
Ah! O código pronto dessa saga de posts está disponível no meu git =)