Symfony - Exemplo de Trabalho
Neste capítulo, aprenderemos como criar um MVC completo baseado BookStore Applicationno Symfony Framework. A seguir estão as etapas.
Etapa 1: Criar um Projeto
Vamos criar um novo projeto chamado “BookStore” no Symfony usando o seguinte comando.
symfony new BookStore
Etapa 2: criar um controlador e uma rota
Crie um BooksController no diretório “src / AppBundle / Controller”. É definido como segue.
BooksController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class BooksController {
/**
* @Route("/books/author")
*/
public function authorAction() {
return new Response('Book store application!');
}
}
Agora, criamos um BooksController e, em seguida, criamos uma visualização para renderizar a ação.
Etapa 3: criar uma visualização
Vamos criar uma nova pasta chamada “Books” no diretório “app / Resources / views /”. Dentro da pasta, crie um arquivo “author.html.twig” e adicione as seguintes alterações.
author.html.twig
<h3> Simple book store application</h3>
Agora, renderize a visualização na classe BooksController. É definido como segue.
BooksController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class BooksController extends Controller {
/**
* @Route("/books/author")
*/
public function authorAction() {
return $this->render('books/author.html.twig');
}
}
A partir de agora, criamos um BooksController básico e o resultado é renderizado. Você pode verificar o resultado no navegador usando a URL “http: // localhost: 8000 / books / author”.
Etapa 4: configuração do banco de dados
Configure o banco de dados no arquivo “app / config / parameters.yml”.
Abra o arquivo e adicione as seguintes alterações.
parameter.yml
# This file is auto-generated during the composer install
parameters:
database_driver: pdo_mysql
database_host: localhost
database_port: 3306
database_name: booksdb
database_user: <database_username>
database_password: <database_password>
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: 0ad4b6d0676f446900a4cb11d96cf0502029620d
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: utf8mb4
Agora, o Doctrine pode se conectar ao seu banco de dados “booksdb”.
Etapa 5: criar um banco de dados
Emita o seguinte comando para gerar o banco de dados “booksdb”. Esta etapa é usada para ligar o banco de dados no Doctrine.
php bin/console doctrine:database:create
Depois de executar o comando, ele gera automaticamente um banco de dados “booksdb” vazio. Você pode ver a seguinte resposta em sua tela.
Isso produzirá o seguinte resultado -
Created database `booksdb` for connection named default
Etapa 6: mapeamento de informações
Crie uma classe de entidade Book dentro do diretório Entity que está localizado em “src / AppBundle / Entity”.
Você pode passar diretamente na classe Book usando anotações. É definido como segue.
Book.php
Adicione o seguinte código ao arquivo.
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name = "Books")
*/
class Book {
/**
* @ORM\Column(type = "integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy = "AUTO")
*/
private $id;
/**
* @ORM\Column(type = "string", length = 50)
*/
private $name;
/**
* @ORM\Column(type = "string", length = 50)
*/
private $author;
/**
* @ORM\Column(type = "decimal", scale = 2)
*/
private $price;
}
Aqui, o nome da tabela é opcional.
Se o nome da tabela não for especificado, ele será determinado automaticamente com base no nome da classe de entidade.
Etapa 7: vincular uma entidade
O Doctrine cria classes de entidade simples para você. Ajuda você a construir qualquer entidade.
Emita o seguinte comando para gerar uma entidade.
php bin/console doctrine:generate:entities AppBundle/Entity/Book
Então você verá o seguinte resultado e a entidade será atualizada.
Generating entity "AppBundle\Entity\Book”
> backing up Book.php to Book.php~
> generating AppBundle\Entity\Book
Book.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name = "Books")
*/
class Book {
/**
* @ORM\Column(type = "integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy = "AUTO")
*/
private $id;
/**
* @ORM\Column(type = "string", length = 50)
*/
private $name;
/**
* @ORM\Column(type = "string", length = 50)
*/
private $author;
/**
* @ORM\Column(type = "decimal", scale = 2)
*/
private $price;
/**
* Get id
*
* @return integer
*/
public function getId() {
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Book
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName() {
return $this->name;
}
/**
* Set author
*
* @param string $author
*
* @return Book
*/
public function setAuthor($author) {
$this->author = $author;
return $this;
}
/**
* Get author
*
* @return string
*/
public function getAuthor() {
return $this->author;
}
/**
* Set price
*
* @param string $price
*
* @return Book
*/
public function setPrice($price) {
$this->price = $price;
return $this;
}
/**
* Get price
*
* @return string
*/
public function getPrice() {
return $this->price;
}
}
Etapa 8: Validação de mapeamento
Depois de criar entidades, você deve validar os mapeamentos usando o seguinte comando.
php bin/console doctrine:schema:validate
Isso produzirá o seguinte resultado -
[Mapping] OK - The mapping files are correct
[Database] FAIL - The database schema is not in sync with the current mapping file.
Como não criamos a tabela Books, a entidade está fora de sincronia. Vamos criar a tabela Books usando o comando Symfony na próxima etapa.
Etapa 9: Criação do esquema
O Doctrine pode criar automaticamente todas as tabelas de banco de dados necessárias para a entidade Livro. Isso pode ser feito usando o seguinte comando.
php bin/console doctrine:schema:update --force
Depois de executar o comando, você verá a seguinte resposta.
Updating database schema...
Database schema updated successfully! "1" query was executed
Agora, valide novamente o esquema usando o seguinte comando.
php bin/console doctrine:schema:validate
Isso produzirá o seguinte resultado -
[Mapping] OK - The mapping files are correct.
[Database] OK - The database schema is in sync with the mapping files.
Etapa 10: Getter e Setter
Conforme visto na seção Vincular uma entidade, o comando a seguir gera todos os getters e setters para a classe Book.
$ php bin/console doctrine:generate:entities AppBundle/Entity/Book
Etapa 11: Buscando objetos do banco de dados
Crie um método em BooksController que exibirá os detalhes dos livros.
BooksController.php
/**
* @Route("/books/display", name="app_book_display")
*/
public function displayAction() {
$bk = $this->getDoctrine()
->getRepository('AppBundle:Book')
->findAll();
return $this->render('books/display.html.twig', array('data' => $bk));
}
Etapa 12: Criar uma visualização
Vamos criar uma visão que aponta para a ação de exibição. Vá para o diretório de visualizações e crie o arquivo “display.html.twig”. Adicione as seguintes alterações no arquivo.
display.html.twig
{% extends 'base.html.twig' %}
{% block stylesheets %}
<style>
.table { border-collapse: collapse; }
.table th, td {
border-bottom: 1px solid #ddd;
width: 250px;
text-align: left;
align: left;
}
</style>
{% endblock %}
{% block body %}
<h2>Books database application!</h2>
<table class = "table">
<tr>
<th>Name</th>
<th>Author</th>
<th>Price</th>
</tr>
{% for x in data %}
<tr>
<td>{{ x.Name }}</td>
<td>{{ x.Author }}</td>
<td>{{ x.Price }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Você pode obter o resultado solicitando a URL “http: // localhost: 8000 / books / display” no navegador.
Resultado
Etapa 13: Adicionar um formulário de livro
Vamos criar uma funcionalidade para adicionar um livro ao sistema. Crie uma nova página, o método newAction no BooksController da seguinte maneira.
// use section
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
// methods section
/**
* @Route("/books/new")
*/
public function newAction(Request $request) {
$stud = new StudentForm();
$form = $this->createFormBuilder($stud)
->add('name', TextType::class)
->add('author', TextType::class)
->add('price', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
return $this->render('books/new.html.twig', array('form' => $form->createView(),));
}
Etapa 14: Criar um formulário de visualização do livro
Vamos criar uma visão que aponta para uma nova ação. Vá para o diretório de visualizações e crie um arquivo “new.html.twig”. Adicione as seguintes alterações no arquivo.
{% extends 'base.html.twig' %}
{% block stylesheets %}
<style>
#simpleform {
width:600px;
border:2px solid grey;
padding:14px;
}
#simpleform label {
font-size:14px;
float:left;
width:300px;
text-align:right;
display:block;
}
#simpleform span {
font-size:11px;
color:grey;
width:100px;
text-align:right;
display:block;
}
#simpleform input {
border:1px solid grey;
font-family:verdana;
font-size:14px;
color:light blue;
height:24px;
width:250px;
margin: 0 0 10px 10px;
}
#simpleform textarea {
border:1px solid grey;
font-family:verdana;
font-size:14px;
color:light blue;
height:120px;
width:250px;
margin: 0 0 20px 10px;
}
#simpleform select {
margin: 0 0 20px 10px;
}
#simpleform button {
clear:both;
margin-left:250px;
background: grey;
color:#FFFFFF;
border:solid 1px #666666;
font-size:16px;
}
</style>
{% endblock %}
{% block body %}
<h3>Book details:</h3>
<div id = "simpleform">
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</div>
{% endblock %}
Ele produzirá a seguinte tela como saída -
Etapa 15: coletar informações do livro e armazená-las
Vamos alterar o método newAction e incluir o código para lidar com o envio do formulário. Além disso, armazene as informações do livro no banco de dados.
/**
* @Route("/books/new", name="app_book_new")
*/
public function newAction(Request $request) {
$book = new Book();
$form = $this->createFormBuilder($book)
->add('name', TextType::class)
->add('author', TextType::class)
->add('price', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$book = $form->getData();
$doct = $this->getDoctrine()->getManager();
// tells Doctrine you want to save the Product
$doct->persist($book);
//executes the queries (i.e. the INSERT query)
$doct->flush();
return $this->redirectToRoute('app_book_display');
} else {
return $this->render('books/new.html.twig', array(
'form' => $form->createView(),
));
}
}
Depois que o livro estiver armazenado no banco de dados, redirecione para a página de exibição do livro.
Etapa 16: Atualizando o livro
Para atualizar o livro, crie uma ação, updateAction e adicione as seguintes alterações.
/**
* @Route("/books/update/{id}", name = "app_book_update" )
*/
public function updateAction($id, Request $request) {
$doct = $this->getDoctrine()->getManager();
$bk = $doct->getRepository('AppBundle:Book')->find($id);
if (!$bk) {
throw $this->createNotFoundException(
'No book found for id '.$id
);
}
$form = $this->createFormBuilder($bk)
->add('name', TextType::class)
->add('author', TextType::class)
->add('price', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$book = $form->getData();
$doct = $this->getDoctrine()->getManager();
// tells Doctrine you want to save the Product
$doct->persist($book);
//executes the queries (i.e. the INSERT query)
$doct->flush();
return $this->redirectToRoute('app_book_display');
} else {
return $this->render('books/new.html.twig', array(
'form' => $form->createView(),
));
}
}
Aqui, estamos processando duas funcionalidades. Se a solicitação contém apenas id, então nós o obtemos do banco de dados e o mostramos no formulário de livro. E, se a solicitação contiver informações completas do livro, atualizamos os detalhes no banco de dados e redirecionamos para a página de exibição do livro.
Etapa 17: Excluindo um objeto
A exclusão de um objeto requer uma chamada ao método remove () do gerenciador de entidade (doutrina).
Isso pode ser feito usando o código a seguir.
/**
* @Route("/books/delete/{id}", name="app_book_delete")
*/
public function deleteAction($id) {
$doct = $this->getDoctrine()->getManager();
$bk = $doct->getRepository('AppBundle:Book')->find($id);
if (!$bk) {
throw $this->createNotFoundException('No book found for id '.$id);
}
$doct->remove($bk);
$doct->flush();
return $this->redirectToRoute('app_book_display');
}
Aqui, excluímos o livro e redirecionamos para a página de exibição do livro.
Etapa 18: Incluir Adicionar / Editar / Excluir Funcionalidade na Página de Exibição
Agora, atualize o bloco do corpo na visualização de exibição e inclua links de inclusão / edição / exclusão conforme a seguir.
{% block body %}
<h2>Books database application!</h2>
<div>
<a href = "{{ path('app_book_new') }}">Add</a>
</div>
<table class = "table">
<tr>
<th>Name</th>
<th>Author</th>
<th>Price</th>
<th></th>
<th></th>
</tr>
{% for x in data %}
<tr>
<td>{{ x.Name }}</td>
<td>{{ x.Author }}</td>
<td>{{ x.Price }}</td>
<td><a href = "{{ path('app_book_update', { 'id' : x.Id }) }}">Edit</a></td>
<td><a href = "{{ path('app_book_delete', { 'id' : x.Id }) }}">Delete</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}
Ele produzirá a seguinte tela como saída -
Symfony é composto por um conjunto de componentes PHP, uma estrutura de aplicativo, uma comunidade e uma filosofia. Symfony é extremamente flexível e capaz de atender a todos os requisitos de usuários avançados, profissionais e uma escolha ideal para todos os iniciantes em PHP.