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.