Obtener entidades desde la base de datos

Teniendo bien configurado el archivo .env, nos colocamos en la raiz de nuestro sitio y ponemos lo siguiente:

 php bin/console doctrine:mapping:import App\Entity annotation --path=src/Entity

Y después regeneramos las entidades para que se pongan los getters y setters:

php bin/console make:entity --regenerate App

Ejemplos de plantillas

Controlador:

 public function index()
    {
        $tabla=['a','b','c'];
        $usuario="Juan";
        $notas=[1,5,23,78,5];
        $actores=['Penelope','Alec','Fernando'];
        return $this->render('plantillas/index.html.twig', [
            'tabla' => $tabla,
            'usuario'=>$usuario,
            'notas'=>$notas,
            'actores'=>$actores
        ]);
    }

Vista:

{% extends 'base.html.twig' %}


{% block body %}
    {# funciones de twig #}

    {{max(1,2,3)}}
    {{max(tabla)}}

    {{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
    {{ random('ABC') }}                         {# example output: C #}
    {{ random() }}                              {# example output: 15386094 (works as the native PHP mt_rand function) #}
    {{ random(5) }}                             {# example output: 3 #}
    {{ random(10) }}                             {# example output: 3 #}

    {{date()|date('d/m/Y')}}
    {{date('2020-1-2')|date('d/m/Y')}}
    {{date('-2days')|date('d/m/Y')}}
    {{date('+2month')|date('d/m/Y')}}

    {# filtros usando | (pipe) #}

    {{usuario}}
    {{usuario | upper}}
    {{usuario | lower}}
    {{usuario | reverse}}
    {{tabla|sort|join(', ')|upper}}


    {% set cadena='4,2,8,4,1,9,34' %}

    {{cadena | split(',') |sort|join(',')}}
    <table>
        <tr><td>Nombre</td></tr>
        {% for actor in actores %}
            <tr><td>{{actor}}</td></tr>
        {% endfor %}
    </table>

    {% set a=5 %}
    {% set b=[1,2,3,4] %}
    {% set c={'nombre':'Juan','Apellidos':'Pi'} %}

    {{a +3}}
    {{a * 3}}
    {{a // 4}} {# division entera #}
    {{a / 4}} {# division normal #}
    {{a **2}} {# potencia (elevar a un número #}
    {{a % 2}}

    {% if a>10 %}
        <h1>A es mayor que 10</h1>
    {% else %}
        <h1>A es menor que 10</h1>
    {% endif %}

    {% if a>10 %}
        <h1>A es mayor que 10</h1>
    {% elseif a>5 %}
        <h1>A es menor que 5</h1>
    {% else %}
        <h1>A vale muy poco</h1>
        <h2>Todo el código que quiera</h2>
    {% endif %}

    {# >,<,>=,<=,!=,==,===, starts width ends with matches #}

    {% if usuario starts with 'J' %}
        <p>Usuario empieza con j</p>
    {% endif %}

    {% if b[0] matches '/\\d+/' %}
        <p>Es numérico</p>
    {% endif %}

    {% if 2 in b %}
        <p>Tenemos 2 en b</p>
    {% endif %}

    {% if 2 is even %}
        <p>Tenemos 2 en b</p>
    {% endif %}
    <ul>
        {% for i in 0..10 if i is odd %}
            <li>{{i}}</li>
            {% endfor %}
            {% for i in 'a'..'z' %}
            <li>{{i}}</li>
            {% endfor %}

        {% for i in b %}
            <li>{{i}}</li>
            {% endfor %}

        {% for i in tabla %}
            <li>{{i}}</li>
            {% endfor %}
    </ul>


{% endblock %}

Symfony ecuación segundo grado

Controlador:

/**
     * @Route("/areas/ecuacion", name="ecuacion")
     */
    public function ecuacion() {
        $request = Request::createFromGlobals();
        $a = $request->request->get('a');
        $b = $request->request->get('b', 1);
        $c = $request->request->get('c', 1);
        if (!is_numeric($c) || !is_numeric($b) || !is_numeric($a)) {
            return $this->render('areas/error.html.twig',
                ['mensaje' => 'Los valores deben ser numéricos',
                'url'=>'/areas']);
        }
        $raiz = $b * $b - 4 * $a * $c;
        if ($raiz < 0) {
            $raiz1 = "No existe";
            $raiz2 = "No existe";
        } elseif ($raiz == 0) {
            $raiz1 = -$b / ($a * 2);
            $raiz2 = $raiz1;
        } else {
            $raiz1 = (-$b + sqrt($raiz)) / ($a * 2);
            $raiz2 = (-$b - sqrt($raiz)) / ($a * 2);
        }

        return $this->render('areas/ecuacion.html.twig', ['raiz1' => $raiz1,
                    'raiz2' => $raiz2,
                    'valores'=>[$a,$b,$c]]);
    }

Vistas:

  <form action="areas/ecuacion" method="post">
        <input type="number" name="a">x<sup>2</sup>+ <input type="number" name="b"> x+
        <input type="number" name="c"><br/>
        <input type="submit">
    </form>
{% extends 'base.html.twig' %}

{% block title %}Hello!{% endblock %}

{% block body %}
    <h1>Las soluciones de la ecuación {{valores[0]}}x<sup>2</sup>+{{valores[1]}}x+{{valores[2]}} son:</h1>
    {% if raiz1=='No existe' %}
        <p>La ecuación no tiene soluciones reales, quizás imaginarias</p>
   <!--     <img src="{{ asset('img/ninguna.gif') }}" alt=""/>-->

    {% elseif raiz1==raiz2 %}
        <p>La ecuación tiene una sóla raiz: {{raiz1}}</p>
   <!--     <img src="{{ asset('img/una.png') }}" alt=""/>-->
    {% else %}
        <p>Raiz 1: {{raiz1}}</p>
        <p>Raiz 2: {{raiz2}}</p>
    <!--    <img src="{{ asset('img/dos.png') }}" alt=""/>-->
    {% endif %}
    <iframe src="http://graph.tk/" id="my_graph" style="width:500px;height:400px">
</iframe>
<script>
var my_graph=document.getElementById("my_graph");

my_graph.onload=function(){
    function g(m){
        my_graph.contentWindow.postMessage(m,"http://graph.tk");
    };
    g("add:{{valores[0]}}x^2+{{valores[1]}}x+{{valores[2]}}");
    g("center:0,0");
}

</script>
{% endblock %}

Symfony obtener parámetros

Controlador:

   /**
     * @Route("/areas/cuadrado", name="cuadrado")
     */
    public function cuadrado() {
        $request = Request::createFromGlobals();
        $lado = $request->request->get('lado');
        return $this->render('areas/cuadrado.html.twig', ['lado' => $lado]);
    }

Vista:

   <h1>Cálculo de áreas</h1>
    <a href="/areas/cuadrado">Cuadrado</a>
    <form action="/areas/cuadrado" method="post">
        <input type="text" name="lado"><input type="submit">
    </form>

Resultado:

{% extends 'base.html.twig' %}

{% block title %}Hello!{% endblock %}

{% block body %}
    <h1>El área del cuadrado es el lado al cuadrado</h1>
    <p>Un cuadrado de lado {{lado}} tiene un área de {{lado*lado}}</p>
{% endblock %}

Symfony pasar html a la vista

Controlador:

/**
     * @Route("/tabla/pintar", name="pintar")
     */
    public function pintar() {
        $request = Request::createFromGlobals();
        $ancho = $request->query->get('ancho');
        $alto = $request->query->get('alto');
        $tabla = "<table>";
        for ($i = 0; $i < $alto; $i++) {
            $tabla .= "<tr>";
            for ($j = 0; $j < $ancho; $j++) {
                $tabla .= "<td>" . ($j + $i * $ancho) . "</td>";
            }
            $tabla .= "</tr>";
        }
        $tabla .= "</table>";
        return $this->render('tabla/tabla.html.twig', [
                    'tabla' => $tabla,
        ]);
    }

vista:

{% extends 'base.html.twig' %}

{% block title %}Tabla{% endblock %}
  {% block styles %}
      <style>
          footer{
              background-color: red;
          }
          </style>
  {% endblock %}
{% block body %}
{# esto es un comentario #}
    <h1>Esta es la tabla que ha pedido</h1>
  
    {{tabla | raw}}
    <img src="{{ asset('img/gato.jpg') }}" alt=""/>

{% endblock %}

CRUD Producto Symfony

Entidad Producto:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProductoRepository")
 */
class Producto
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $nombre;

    /**
     * @ORM\Column(type="integer")
     */
    private $precio;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $stock;

    
    public function getId(): ?int
    {
        return $this->id;
    }

    public function getNombre(): ?string
    {
        return $this->nombre;
    }

    public function setNombre(string $nombre): self
    {
        $this->nombre = $nombre;

        return $this;
    }

    public function getPrecio(): ?int
    {
        return $this->precio;
    }

    public function setPrecio(int $precio): self
    {
        $this->precio = $precio;

        return $this;
    }

    public function getStock(): ?int
    {
        return $this->stock;
    }

    public function setStock(?int $stock): self
    {
        $this->stock = $stock;

        return $this;
    }
}

Controlador:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Producto;

class ProductoController extends AbstractController {

    /**
     * @Route("/producto", name="producto")
     */
    public function index() {
        /*
          $entityManager = $this->getDoctrine()->getManager();

          for ($i = 1; $i <= 10; $i++) {
          $producto = new Producto();
          $producto->setNombre('Producto '.$i);
          $producto->setPrecio($i);

          // Guardamos el producto
          $entityManager->persist($producto);
          }
          // Actualizamos los datos en la BD
          $entityManager->flush();
         */
        /*
          //Producto es un objeto del tipo Producto Entity
          //Con sus propiedades y métodos (concretamente los get y set de las columnas)
          $producto = $this->getDoctrine()
          ->getRepository(Producto::class)
          ->find($id);
          $producto->setNombre('Nuevo nombre cool para mi producto ¡Mola!');
          $entityManager = $this->getDoctrine()->getManager();
          $entityManager->remove($producto);
          $entityManager->flush();

          $producto = $this->getDoctrine()
          ->getRepository(Producto::class)
          ->findOneBy(['nombre'=>'Producto 5']);


         * 
         */
        $productos = $this->getDoctrine()
                ->getRepository(Producto::class)
                ->findAll();
        $salida = [];
        foreach ($productos as $producto) {
            $salida[] = [$producto->getId(),
                $producto->getNombre(),
                $producto->getPrecio()];
        }
        return $this->render('producto/index.html.twig', [
                    'productos' => $salida]);
    }

    /**
     * @Route("/producto/nuevo", name="nuevo")
     */
    public function nuevo() {
        $request = Request::createFromGlobals();
        $nombre = $request->request->get('nombre');
        $precio = $request->request->get('precio');
        $stock = $request->request->get('stock');
        $id = '';
        if (!empty($nombre) && !empty($precio)) {
            //Añadir el producto
            $producto = new Producto();
            $producto->setNombre($nombre);
            $producto->setPrecio($precio);
            if (empty($stock)) {
                $stock = 0;
            }
            $producto->setStock($stock);
            $entityManager = $this->getDoctrine()->getManager();
            // Guardamos el producto
            $entityManager->persist($producto);

            // Actualizamos los datos en la BD
            $entityManager->flush();
            $id = $producto->getId();
        }
        return $this->render('producto/nuevo.html.twig', ['id' => $id]);
    }

    /**
     * @Route("/producto/eliminar/{id}", name="eliminar")
     */
    public function eliminar(Producto $producto) {

        $nombre = $producto->getNombre();

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->remove($producto);
        $entityManager->flush();

        return $this->render('producto/eliminar.html.twig', ['nombre' => $nombre]);
    }

    /**
     * @Route("/producto/editar/{id}", name="editar")
     */
    public function editar(Producto $producto) {

        $request = Request::createFromGlobals();
        $nombre = $request->request->get('nombre');
        $precio = $request->request->get('precio');
        $stock = $request->request->get('stock');
        if (!empty($nombre) && !empty($precio)) {
            $producto->setNombre($nombre);
            $producto->setPrecio($precio);
            if (empty($stock)){$stock=0;}
            $producto->setStock($stock);
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->flush();
        }
        return $this->render('producto/editar.html.twig', [
                    'nombre' => $producto->getNombre(),
                    'precio' => $producto->getPrecio(),
                    'stock' => $producto->getStock(),
        ]);
    }

}

Plantillas:

index:

{% extends 'base.html.twig' %}

{% block title %}{% endblock %}

{% block body %}
    <div class="container">
        <h1>Productos</h1>
        <a href="/producto/nuevo" class="btn btn-success">Nuevo producto</a>
        <table class="table">
            <tr><td>Id</td><td>Nombre</td><td>Precio</td><td>Acciones</td></tr>
            {% for producto in productos %}
                <tr><td>{{producto[0]}}</td><td>{{producto[1]}}</td><td>{{producto[2]}}</td>
                    <td><a href="/producto/editar/{{producto[0]}}" class="btn btn-info">Editar</a> 
                        <a href="/producto/eliminar/{{producto[0]}}" class="btn btn-danger">Eliminar</a></td></tr> 
                {% endfor %}
        </table>
    </div>
{% endblock %}

nuevo

{% extends 'base.html.twig' %}

{% block title %}{% endblock %}

{% block body %}
    <div class="container">
        <h1>Nuevo Producto</h1>
        {% if id %}
            <div class="alert alert-success alert-dismissible">
                <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                <strong>Correcto</strong> Se ha insertado con éxito el producto con id {{id}}.
            </div>
        {% endif %}

        <form method="post">
            <div class="form-group">
                Nombre: <input  class="form-control" type="text" name="nombre"></div>
            <div class="form-group">
                Precio: <input  class="form-control" type="text" name="precio"></div>
            <div class="form-group">
                Stock: <input  class="form-control" type="text" name="stock"></div>
            <input type="submit" class="btn btn-info">
        </form>
    </div>
{% endblock %}

editar:

{% extends 'base.html.twig' %}

{% block title %}{% endblock %}

{% block body %}
    <div class="container">
        <h1>Editar Producto</h1>
      

        <form method="post">
            <div class="form-group">
                Nombre: <input  class="form-control" type="text" value="{{nombre}}" name="nombre"></div>
            <div class="form-group">
                Precio: <input  class="form-control" type="text" value="{{precio}}" name="precio"></div>
            <div class="form-group">
                Stock: <input  class="form-control" type="text" value="{{stock}}" name="stock"></div>
            <input type="submit" class="btn btn-info">
        </form>
            <a href="/producto">Volver al listado</a>
    </div>
{% endblock %}

eliminar:

{% extends 'base.html.twig' %}

{% block title %}{% endblock %}

{% block body %}
    <div class="container">
        <h1>Eliminar Producto</h1>
        <p>Has eliminado el producto <b>{{nombre}}</b></p>
        <a href="/producto">Volver al listado</a>
    </div>
{% endblock %}

Entidades y bases de datos

En el archivo de configuración tenemos que poner la ruta a nuestra base de datos:

.env

DATABASE_URL=mysql://root:@127.0.0.1:3306/symfony

Para crear una entidad usamos lo siguiente:

php bin/console make:entity

Nos preguntará el nombre de la entidad y los campos ¡Ojo! que el id ya lo crea él.

Cuando ya hayamos creado todas las entidades que necesitamos tenemos que hacer una migración:

php bin/console make:migration

Esto nos crea un archivo Migration dentro de src/MIgrations con el sql que se tendría que ejecutar. Todavía no se ha mandado a la base de datos, se podría revisar. Para ejecutarlo tenemos que hacer lo siguiente:

php bin/console doctrine:migrations:migrate

Ojo, que esto nos afecta a la base de datos y nos podemos cargar cosas.

Aquí el mapeo de tipos: https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#doctrine-mapping-types

Para crear una entidad en la base de datos. Primero la usamos:

use App\Entity\Producto;

Y después hacemos lo siguiente:

$entityManager = $this->getDoctrine()->getManager();

$product = new Producto();
$product->setNombre(‘Keyboard’);
$product->setPrecio(1999);

// Guardamos el producto
$entityManager->persist($product);

// Actualizamos los datos en la BD
$entityManager->flush();

Para buscar un producto por id:

$product = $this->getDoctrine()
->getRepository(Producto::class)
->find($id);

Buscar un elemento:

$product = $this->getDoctrine()
->getRepository(Producto::class)
->findOneBy([‘nombre’ => ‘Keyboard’]);

Otras opciones:
$product = $this->getDoctrine()
->getRepository(Producto::class)
->findBy(
[‘name’ => ‘Keyboard’],
[‘price’ => ‘ASC’]
);

// Todos
$product = $this->getDoctrine()
->getRepository(Producto::class)->findAll();

https://symfony.com/doc/current/doctrine.html

Como hacer ingeniería inversa, obtener las entidades de una base de datos ya existente.

https://symfony.com/doc/current/doctrine/reverse_engineering.html

Plantillas con twig

Symfony usa como plantillas la librería externa twig.

Dispone de una serie de elementos que nos permiten hacer algo de programación pero toda orientada al diseño. Así, tenemos bucles o estructuras de control, filtros que podemos aplicar a las variables, pero no disponemos de las funciones de php.

Para imprimir una variable usamos {{ … }}

Para una etiqueta de programación usamos {% … %}

Para un comentario usamos {# … #}

Algunos ejemplos:

{% if users %}
    <ul>
        {% for user in users %}
            <li>{{ user.username|e }}</li>
        {% endfor %}
    </ul>
{% endif %}
{% if temperature > 18 and temperature < 27 %}
    <p>It's a nice day for a walk in the park.</p>
{% endif %}
{% for i in 0..10 %}
    * {{ i }}
{% endfor %}