Symfony - Ejemplo funcional
En este capítulo, aprenderemos cómo crear un MVC completo BookStore Applicationen Symfony Framework. Los siguientes son los pasos.
Paso 1: crea un proyecto
Creemos un nuevo proyecto llamado "BookStore" en Symfony usando el siguiente comando.
symfony new BookStore
Paso 2: crear un controlador y una ruta
Cree un BooksController en el directorio "src / AppBundle / Controller". Se define como sigue.
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!');
}
}
Ahora, hemos creado un BooksController, luego cree una vista para representar la acción.
Paso 3: crear una vista
Creemos una nueva carpeta llamada "Libros" en el directorio "app / Resources / views /". Dentro de la carpeta, cree un archivo “author.html.twig” y agregue los siguientes cambios.
author.html.twig
<h3> Simple book store application</h3>
Ahora, renderice la vista en la clase BooksController. Se define como sigue.
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 ahora, hemos creado un BooksController básico y se representa el resultado. Puede comprobar el resultado en el navegador utilizando la URL "http: // localhost: 8000 / books / author".
Paso 4: configuración de la base de datos
Configure la base de datos en el archivo “app / config / parameters.yml”.
Abra el archivo y agregue los siguientes cambios.
parámetro.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
Ahora, Doctrine puede conectarse a su base de datos "booksdb".
Paso 5: crear una base de datos
Emita el siguiente comando para generar la base de datos "booksdb". Este paso se usa para vincular la base de datos en Doctrine.
php bin/console doctrine:database:create
Después de ejecutar el comando, genera automáticamente una base de datos "booksdb" vacía. Puede ver la siguiente respuesta en su pantalla.
Producirá el siguiente resultado:
Created database `booksdb` for connection named default
Paso 6: información de mapeo
Cree una clase de entidad Libro dentro del directorio Entity que se encuentra en "src / AppBundle / Entity".
Puede pasar directamente la clase de libro utilizando anotaciones. Se define como sigue.
Book.php
Agregue el siguiente código en el archivo.
<?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;
}
Aquí, el nombre de la tabla es opcional.
Si no se especifica el nombre de la tabla, se determinará automáticamente en función del nombre de la clase de entidad.
Paso 7: vincular una entidad
Doctrine crea clases de entidad simples para ti. Te ayuda a construir cualquier entidad.
Emita el siguiente comando para generar una entidad.
php bin/console doctrine:generate:entities AppBundle/Entity/Book
Luego verá el siguiente resultado y la entidad se actualizará.
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;
}
}
Paso 8: Validación del mapeo
Después de crear las entidades, debe validar las asignaciones con el siguiente comando.
php bin/console doctrine:schema:validate
Producirá el siguiente resultado:
[Mapping] OK - The mapping files are correct
[Database] FAIL - The database schema is not in sync with the current mapping file.
Como no hemos creado la tabla Libros, la entidad no está sincronizada. Creemos la tabla Books usando el comando de Symfony en el siguiente paso.
Paso 9: Crear esquema
Doctrine puede crear automáticamente todas las tablas de la base de datos necesarias para la entidad Libro. Esto se puede hacer usando el siguiente comando.
php bin/console doctrine:schema:update --force
Después de ejecutar el comando, verá la siguiente respuesta.
Updating database schema...
Database schema updated successfully! "1" query was executed
Ahora, vuelva a validar el esquema con el siguiente comando.
php bin/console doctrine:schema:validate
Producirá el siguiente resultado:
[Mapping] OK - The mapping files are correct.
[Database] OK - The database schema is in sync with the mapping files.
Paso 10: Getter y Setter
Como se ve en la sección Vincular una entidad, el siguiente comando genera todos los captadores y definidores para la clase Libro.
$ php bin/console doctrine:generate:entities AppBundle/Entity/Book
Paso 11: Obtener objetos de la base de datos
Cree un método en BooksController que muestre los detalles de los libros.
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));
}
Paso 12: crear una vista
Creemos una vista que apunte a mostrar acción. Vaya al directorio de vistas y cree el archivo "display.html.twig". Agregue los siguientes cambios en el archivo.
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 %}
Puede obtener el resultado solicitando la URL “http: // localhost: 8000 / books / display” en el navegador.
Resultado
Paso 13: Agregar un formulario de libro
Creemos una funcionalidad para agregar un libro al sistema. Cree una página nueva, método newAction en BooksController de la siguiente manera.
// 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(),));
}
Paso 14: Crear una vista para formulario de libro
Creemos una vista que apunte a una nueva acción. Vaya al directorio de vistas y cree un archivo "new.html.twig". Agregue los siguientes cambios en el archivo.
{% 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 %}
Producirá la siguiente pantalla como salida:
Paso 15: recopile la información del libro y guárdela
Cambiemos el método newAction e incluyamos el código para manejar el envío del formulario. Además, almacene la información del libro en la base de datos.
/**
* @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(),
));
}
}
Una vez que el libro se almacena en la base de datos, redirige a la página de visualización del libro.
Paso 16: Actualización del libro
Para actualizar el libro, cree una acción, actualiceAcción y agregue los siguientes cambios.
/**
* @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(),
));
}
}
Aquí, estamos procesando dos funcionalidades. Si la solicitud solo contiene id, la obtenemos de la base de datos y la mostramos en el formulario de libro. Y, si la solicitud contiene información completa del libro, actualizamos los detalles en la base de datos y lo redireccionamos a la página de visualización del libro.
Paso 17: Eliminar un objeto
Eliminar un objeto requiere una llamada al método remove () del administrador de la entidad (doctrine).
Esto se puede hacer usando el siguiente código.
/**
* @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');
}
Aquí, eliminamos el libro y lo redirigimos a la página de visualización del libro.
Paso 18: Incluya la función Agregar / Editar / Eliminar en la página de visualización
Ahora, actualice el bloque del cuerpo en la vista de visualización e incluya incluir agregar / editar / eliminar enlaces de la siguiente manera.
{% 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 %}
Producirá la siguiente pantalla como salida:
Symfony se compone de un conjunto de componentes PHP, un marco de aplicación, una comunidad y una filosofía. Symfony es extremadamente flexible y capaz de cumplir con todos los requisitos de usuarios avanzados, profesionales y una opción ideal para todos los principiantes con PHP.