Listar las empresas

9/17

Lectura

La vista del administrador

En la clase anterior comenzamos a desarrollar la funcionalidad del usuario administrador, aprendiste c贸mo crear un nuevo controlador, c贸mo vincularlo a una URL y c贸mo desarrollar un template.

En esta clase vamos a darle concretud mediante un ejemplo de nuestro proyecto: el listado de las empresas registradas.

El listado de empresas

Usualmente las URLs que mapean a m茅todos index tienen como objetivo mostrar listados completos de objetos, en nuestro caso, se trata de ofertas.

As铆 que, realicemos las modificaciones que necesitamos para lograr ello.

Lo primero que vamos a requerir es acceder a las ofertas que existen, para ello tendremos que valernos de uno de los servicios que Symfony (m谩s bien Doctrine) provee: el EntityManager.

En Symfony el concepto de Servicio es muy importante: se trata de clases que realizan alguna funci贸n, aunque su estado no es importante.

B谩sicamente podr铆as pensar que las clases de una aplicaci贸n Symfony se clasifican en Entidades y Servicios.

Una de las caracter铆sticas m谩s interesantes que ha introducido Symfony a partir de la versi贸n 4 es el autowiring.

Se trata de un mecanismo que permite que las instancias de los objetos servicio disponibles en el Contenedor de Dependencias (otro de los componentes core del framework) sean inyectadas a cualquier m茅todo p煤blico que las requiera con s贸lo definirlas como par谩metro.

El m茅todo index de CompanyController ahora debe declararse as铆:

public function index(EntityManagerInterface $entityManager)
{
$companies = $entityManager
       ->getRepository(Company::class)
       ->findAll();

   return $this->render('company/index.html.twig', [
       'companies' => $companies,
   ]);
}


Toda la 鈥渕agia鈥 del autowiring se basa en el uso extensivo de type-hinting (realmente no se trata de magia como te habr谩s imaginado).

El Contenedor de Dependencias identifica a cada servicio por su clase (o interface), de esa forma es sencillo determinar los argumentos que deber谩n utilizarse al momento de realizar la invocaci贸n de estos m茅todos.

隆Ah! Casi lo olvido, hay un par de sentencias use que debes agregar al comienzo (ver nota):

  • use Doctrine\ORM\EntityManagerInterface;
  • use App\Entity\Company;

Y ahora s贸lo nos queda adaptar el template templates/company/index.html.twig:

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

{% block title %}Empresas registradas{% endblock %}

{% block body %}
<style>
   .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
   .example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>

<div class="example-wrapper">
   <h1>Empresas registradas</h1>

    {% if companies|length > 0 %}
    <ul>
       {% for company in companies %}
       <li>{{ company.name }} - {{ company.email }}</li>
       {% endfor %}
    </ul>
    {% else %}
       <p>A煤n no hay empresas</p>
    {% endif %}
</div>
{% endblock %}

Si refrescas tu navegador ver谩s:

No hay empresas registradas

Lo cual es l贸gico鈥 a煤n no se ha creado ninguna empresa :p.

Creaci贸n de una empresa

Para crear empresas ser谩 necesario contar con:

  1. Un nuevo m茅todo.
  2. Un nuevo template.

De modo que, 隆manos a la obra!

Antes de empezar a tirar c贸digo, sabemos que necesitaremos un formulario para ingresar los datos.

Para crearlo usaremos el comando php bin/console make:form.

En el nombre del formulario usaremos CompanyType(el sufijo Type es una convenci贸n de Symfony) y lo asociaremos a la entidad Company.

De este modo obtendremos una nueva clase src/Form/CompanyType, la cual contendr谩 los objetos que se usar谩n para crear el HTML del formulario (tanto en la creaci贸n de ofertas como en la edici贸n).

Si vemos el formulario construido notaremos que falta algo鈥 驴C贸mo har谩 el usuario para enviar los datos sin un bot贸n de submit?

De modo que mejor lo agregamos al m茅todo CompanyType::buildForm():

$builder
   ->add('name')
   ->add('email')
   ->add('save', SubmitType::class, [
       'label' => 'Guardar',
   ])
;

Ahora s铆, armemos el nuevo m茅todo en CompanyController:

/**
* @param Request $request
* @param EntityManagerInterface $entityManager
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
* @Route("/company/new", name="company_new")
*/
public function create(Request $request, EntityManagerInterface $entityManager)
{
   $company = new Company();
   $form = $this->createForm(CompanyType::class);
   $form->setData($company);
   $form->handleRequest($request);

   if ($form->isSubmitted() && $form->isValid()) {
       $company = $form->getData();

       $entityManager->persist($company);
       $entityManager->flush();

       return $this->redirectToRoute('company');
   }

   return $this->render('company/new.html.twig', [
       'form' => $form->createView(),
   ]);
}

隆Listo! 隆Nuestro administrador ya puede crear empresas!

La pregunta que surge es 驴s贸lo el administrador puede crear empresas?

Pues as铆 deber铆a ser pero con lo que hicimos hasta ahora cualquiera con la URL correcta puede鈥 hay que remediar eso.

En la pr贸xima clase construiremos un sistema de login con el que limitaremos el acceso a las partes sensibles de nuestra aplicaci贸n.

隆All谩 vamos!

Nota

El c贸digo mostrado lo he generado utilizando un IDE que agrega autom谩ticamente las sentencias use. Si no cuentas con una herramienta como esta es posible que te encuentres con errores al ejecutar el c贸digo tal cual se ve. No te preocupes, Symfony te dar谩 un mensaje sumamente claro respecto de qu茅 debes corregir para que todo funcione.

Aportes 13

Preguntas 1

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Buenas, ya que no est谩 la template new.html.twig os dejo por aqu铆 la que he montado yo 馃槂

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

{% block title %}Nuevas empresas{% endblock %}

{% block body %}
<style>
   .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
   .example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>

<div class="example-wrapper">
   <h1>Nuevas empresas</h1>

    {{ form(form) }}

</div>
{% endblock %}

Bufff, muy escasa la explicaci贸n, trato de hacer comparaciones con Laravel para quienes lo conocen les sea m谩s f谩cil relacionar conceptos.

Pr谩cticamente el autowiring es la inyecci贸n de dependencias de Laravel, es decir, mediante el nombre de la clase puedes pasar por el par谩metro de una funci贸n lo que necesites.

Por cierto, esto tampoco se explica pero para ver la p谩gina tendr铆as que entrar a /company/new pero te dar谩 un error porque no tenemos ning煤n template para eso, cosa qu茅 falt贸 explicar鈥

Es m谩s f谩cil si usamos

php bin/console make:crud

para crear el controlador con todo lo necesario para listar, editar, modificar y borrar y, adem谩s, nos crea el formType y todas las vistas necesarias sin tener que rompernos tanto la cabeza

Les dejo mi CompanyController.php con los respectivos use funcionando:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Company;
use App\Form\CompanyType;
use Symfony\Component\HttpFoundation\Request;

class CompanyController extends AbstractController
{
    /**
     * @Route("/company", name="company")
     */
    public function index(EntityManagerInterface $entityManager) {
        $companies = $entityManager
            ->getRepository(Company::class)
            ->findAll();

        return $this->render('company/index.html.twig', [
            'companies' => $companies,
        ]);
    }

    /**
    * @param Request $request
    * @param EntityManagerInterface $entityManager
    * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
    * @Route("/company/new", name="company_new")
    */
    public function create(Request $request, EntityManagerInterface $entityManager) {
        $company = new Company();
        $form = $this->createForm(CompanyType::class);
        $form->setData($company);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $company = $form->getData();

            $entityManager->persist($company);
            $entityManager->flush();

            return $this->redirectToRoute('company');
        }

        return $this->render('company/new.html.twig', [
            'form' => $form->createView(),
        ]);
    }

}

Este curso se merece una mejor explicacion y darle un poquito mas de cari帽o. No le quito el esfuerzo dado al curso, pero no creo que sea la mejor ruta para aprender, si colocase mini videos o de alguna forma explicar lo que se va a usar en el curso, no solo colocar copie esto y listo, necesitamos esto copie y listo.

Es incre铆ble, me toco leer la explicaci贸n del profesor dos veces, luego todos los comentarios de los compa帽eros, solucionar cada error y lo logr茅.
Ya puedo adicionar empresas.
De no ser por la ayuda de los compa帽eros, hubiera sido muy dif铆cil completar esta clase.

Si no se les muesra el formulario y les sale un error de que no encuentra la ruta, la soluci贸n es:

A帽adir un archivo llamado: new.html.twig dentro de templates/company

Dentro de ese archivo colocar esto:

{{ form(form) }}

Con eso deber铆a pintarse su formulario

Un poco escasa esta parte, ni vista ni declaraci贸n del use.

Para el Request, usar: use Symfony\Component\HttpFoundation\Request;

Tampoco est谩 implementado el arrayAccess y en mi caso da error, as铆 quedar铆a mi c贸digo a帽adiendo los m茅todos de la implementaci贸n:

use App\Repository\CompanyRepository;
use ArrayAccess;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=CompanyRepository::class)
 */
class Company implements ArrayAccess
public function offsetExists($offset)
    {
        // TODO: Implement offsetExists() method.
    }


    public function offsetGet($offset)
    {
        // TODO: Implement offsetGet() method.
    }


    public function offsetSet($offset, $value)
    {
        // TODO: Implement offsetSet() method.
    }


    public function offsetUnset($offset)
    {
        // TODO: Implement offsetUnset() method.
    }

Buen d铆a, no hay referencias sobre el template de new company.

para ver el formulario se necesita agregar

use Symfony\Component\Form\Extension\Core\Type\SubmitType;

Como ya comentaron otros ojo porque aqu铆 faltan varias cosas:

  1. relacionado a las notas del profesor, no se est谩 la indicaci贸n de agregar los 鈥渦se鈥 para que funcione el autowiring. Tuve que agregar varios (detallados abajo por RetaxMaster. Adem谩s tuve que agregar:

use Symfony\Component\Form\Extension\Core\Type\SubmitType;

En CompanyType.php

  1. No se indica crear el nuevo template (company/new.html.twig). Si no encuentra ese archivo no va a funcionar.

  2. aunque est谩 en el bloque de c贸digo de muestra al crear el nuevo m茅todo en CompanyController, no se hace menci贸n a la importancia de la ruta ni el uso de par谩metros que all铆 se muestra.

Creo que aprendo m谩s y mejor cuando los contenidos son v铆deos y puedo desarrollar las actividades a la par con el docente.