20 trucos para Symfony 4
Trucos de Symfony 4 que te ayudarán a resolver algún que otro problema

En este artículo quiero recoger algunos de esos trucos o atajos que podemos usar en Symfony y que, aunque estén bien documentados, es posible que no os suenen si no habéis buceado por su documentación. Así que vamos a ello! Espero descubriros alguno que no conozcáis!
1. Crear excepciones HTTP directamente desde el controlador
Symfony permite crear excepciones relacionadas con algunos de los errores HTTP más típicos directamente desde el controlador sin tener que escribir new Tipo de Excepción
:
throw $this->createNotFoundException('message'); // 404throw $this->createAccessDeniedException('message'); // 403
2. Bindear parámetros por su nombre
Con la llegada del autowiring a Symfony, inyectar servicios pasó a resultar muy sencillo gracias a la posibilidad de referirnos a ellos por su clase o interfaz que implementan en el constructor de la clase donde queremos inyectarlos.
Sin embargo, también es posible decirle a Symfony que cuando encuentre en el constructor de un servicio un parámetro nombrado de forma específica, lo bindee con lo que nosotros le digamos:
services: _defaults: autowire: true autoconfigure: true bind: $clientSecret: '%clientSecret%'
$myAwesomeService: '@my_awersome_service'
3. Autoinvocar controladores
Si queremos que nuestros controladores sean first-class es posible recurrir al método mágico__invoke
de PHP para que en la definición de la ruta no sea necesario especificar el método del controlador asociado.
Es decir, podemos definir una ruta del siguiente modo:
a_route: path: /some-path controller: App\Controller\AnyController
De modo que en nuestro controlador solo sea necesario escribir un método:
class AnyController extends AbstractController { public function __invoke( // services ) {
// code
De este modo nuestros controladores siguen el principio de responsabilidad única y escribir tests sobre ellos se vuelve bastante más limpio (pues solo hay que comprobar una funcionalidad).
4. Inyectar repositorios
Pese a que estamos acostumbrados a inyectar en nuestros servicios directamente la interfaz EntityManagerInterface
y de ahí pedir el repositorio de nuestra clase mediante getRepository
, recordad que en Symfony todas las clases que definamos son servicios (salvo las que especifiquemos que no), por lo que también podemos inyectarlos directamente:
construct(AnyRepository $anyRepository) {
// constructor
}
Esto permite hacer cosas tan interesantes como decorar repositorios:
5. Ordenar consultas a Doctrine
Otra de esas cosas que suelen resultar bastante útiles es la posibilidad de especificar el orderBy
y el limit
al emplear el método findBy
de nuestros repositorios de Doctrine, lo cual nos evitará tener que escribir la consulta:
$repository->findBy(
[ 'field' => 'value'],
[ 'fieldToOrder' => 'ASC'],
$limit,
$offset);
6. Definir un commando más rápido (aún)
Ahora es posible prescindir del método configure
cuando escribimos comandos para definir el nombre asociado al comando y que emplearemos cuando queramos ejecutarlo desde consola.
Tan solo basta con definir la propiedad estática:
protected static $defaultName = 'app:command-name';
y ya podremos ejecutar nuestro comando.
7. Inyectar servicios en comandos
También, gracias al autowiring y a que los comandos también son definidos como servicios, es posible inyectar otros servicios en ellos directamente a través del constructor sin necesidad de extender la clase ContainerAwareCommand
:
public function __construct(ServiceInterface $aService) { $this->aService = $aService; parent::__construct();}
Nota. Recordad que ahora los comandos deben extender de la clase:
use Symfony\Component\Console\Command\Command;
8. Incluir archivos generados por webpack
La nueva versión de Webpack Encore trae entre sus principales novedades una nueva forma de incluir los archivos que generemos.
A partir de ahora, en vez de tener que escribir
<link rel="stylesheet" href="{{ asset('build/file.css') }}"><script src="{{ asset('build/file.js') }}"></script>
para incluir los css / js generados, basta con:
{{ encore_entry_link_tags('entryName') }}{{ encore_entry_script_tags('entryName') }}
Como veis, ¡mucho más sencillo!
9. Inicialización de los tests
Aunque probablemente esto ya lo conozcáis, no está de más recordar la forma en que podemos realizar ciertas acciones antes de la ejecución de cada test así como deshacerlas una vez finalizadas (por ejemplo, igual queremos situar la base de datos en un cierto estado para ese test en concreto). Para ello basta con implementar los métodos:
protected function setUp() {}protected function tearDown() {}
El primero se ejecutará antes de cada test definido dentro de la clase mientras que el segundo lo hará cada vez que finalice la ejecución de uno.
Realmente muy útil para ciertas pruebas.
10. Comando make para generar entidades
Esto fue un amor a primera vista cuando me encontré con él. A partir de ahora generar entidades es tan sencillo como ejecutar el comando:
bin/console make:entity
Con él podremos definir las propiedades y relaciones de nuestras entidades por línea de comandos, lo cual generará directamente tanto la clase como su repositorio. ¡Perfecto para ahorrar tiempo!
11. Comando make para generar administradores
Y si el anterior sirve para ahorra tiempo generando entidades, si estamos usando SonataAdmin para generar el panel de administración de nuestra aplicación, podemos ejecutar:
bin/console make:sonata:admin
para generar directamente el servicio y la clase asociada para la entidad cuyo administrador queremos generar.
12. Enumerados
Esto no es un truco propio de Symfony pero quería dejaros este boilerplate que uso habitualmente para definir tipos enumerados en mi aplicación (perfecto para definir opciones estáticas dentro de la aplicación):
<?phpnamespace App\Enum;class SimpleEnum { private static $types = [
'a' => self::A,
'b' => self::B
]; const A = 1;
const B = 2; public static function getValues(){
return self::$types;
} public static function fromString($index){
return self::$types[$index];
} public static function toString($value){
return array_search($value, self::$types);
}
}
13. Traducir las rutas
Esta ha sido una de las novedades que más he agradecido, ya que añade soporte nativo para traducir las rutas de nuestra aplicación.
Basta con definir la ruta del siguiente modo:
route_name:
controller: App\Controller\AnyController::actionName
path:
es: /path
en: /translated-path
De modo que cuando generemos la ruta empleando la función path
, ésta será generada teniendo en cuenta el valor del locale actual.
14. Doctrine migrations
Aunque ya es el sistema recomendado por la documentación de Symfony cuando trabajamos con Doctrine, no está de más recordar que las Doctrine Migrations nos permiten tener una versionado de nuestra base de datos, de modo que podamos navegar por las distintas versiones que hemos ido generando de forma bastante sencilla.
Para ello basta con emplear los comandos:
bin/console make:migrationbin/console doctrine:migrations:migrate
Lo cual irá generando los correspondientes archivos de migración en la carpeta Migrations
de nuestro proyecto así como actualizará la tabla migration_versions
para llevar el control de en qué versión nos encontramos.
15. Devolver un código de error HTTP al renderear un archivo twig
Cuando queramos devolver un código de error a la vez que devolvemos el HTML asociado a un archivo twig basta con devolver lo siguiente:
return new Response( $this->renderView( 'error.html.twig', ['error' => $e->getMessage()], Response::HTTP_BAD_REQUEST ));
Por cierto, echad un ojo a las constantes definidas por la clase Response
para devolver los errores y no tenerlos hardcodeados.
16. Comprobar si un usuario ha iniciado sesión
Recordad que para comprobar en un controlador si el usuario que ha realizado la petición ha iniciado sesión no sirve con:
$user = $this->getUser();if ($user) {}
sino que tendremos que recurrir al método:
$this->isGranted('IS_AUTHENTICATED_FULLY')
con el fin de asegurarnos de que el usuario posee una sesión.
Además, tenemos el atajo
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
para lanzar una excepción 403 cuando el usuario no posea el rol que estamos comprobando.
17. Property Accessor
Una de los componentes más útiles y que más suelen pasar desapercibidos es el conocido como PropertyAcccess
, un componente que nos permite abstraer la lógica a la hora de acceder a propiedades de objetos y arrays de modo que determinadas partes de nuestro código queden mucho más limpias.
De hecho con la recién salida del horno versión 4.3 de Symfony su rendimiento ha mejorado aún más por lo que os recomiendo que le echéis un ojo porque siempre viene bien conocer este tipo de herramientas.
18. Doctrine event listener
Los Doctrine Event Listener nos permiten realizar acciones durante el ciclo de vida de las entidades controladas por Doctrine. Para ello existen numerosos eventos (como por ejemplo prePersist
, preUpdate
u onFlush
a los que podemos engancharnos mediante servicios para realizar en ellos las operaciones que necesitemos.
De hecho, en estos eventos tendremos acceso a un argumento que nos proveerá de un EntityManager
así como podremos acceder a los cambios realizados en las entidades mediante las UnitOfWork
tal y y como os conté en el artículo donde os explicaba la forma de detectar cambios en una entidad:
Os aconsejo que le echéis un ojo a la documentación oficial de Doctrine para saber qué operaciones podéis realizar en cada evento (ya que, por ejemplo, modificar relaciones no está permitido en casi ninguno de ellos).
19. Traducir fechas en twig
Este es uno de mis favoritos, ya que por defecto el filtro date
de Twig no traduce las fechas al idioma que hemos escogido, por lo que es necesario recurrir a las Twig Extensions
para obtener dicha funcionalidad.
Si no las tenéis instaladas podéis hacerlo mediante composer
:
composer require twig/extensions
y generar un archivo twig_extensions.yaml
en la ruta config/packages
con el siguiente contenido:
services:_defaults: public: false autowire: true autoconfigure: true#Twig\Extensions\ArrayExtension: ~Twig\Extensions\DateExtension: arguments: ['@translator']Twig\Extensions\IntlExtension: ~#Twig\Extensions\TextExtension: ~
Como podéis ver he activado dos extensiones:
DateExtension
, la cual permite usar el filtrotime_diff
y así obtener la diferencia entre la fecha actual y la que le pasemos. Necesita como argumento una interfazTranslator
y que en la carpetatranslations
de nuestro proyecto generemos un archivodate.LANG.yaml
con las traducciones.IntlExtension
, la cual permite traducir fechas mediante el filtrolocalizeddate
y cuyo uso podéis ver en el siguiente enlace:
20. Los CacheAdapters
Finalmente, otro de los componentes más útiles que Symfony trae de gratis son los CacheAdapter
de los cuales ya os hablé en este artículo:
Y que simplifican el uso de los distintos tipo de caché que podemos instalar en el servidor al proveer una misma interfaz para ellos. Muy muy útiles.
Final
Espero que estos trucos os hayan servido bien para descubrir algo nuevo bien para refrescar cómo se hace algo. Si tenéis alguno que queráis compartir no dudéis en dejarlo en los comentarios!
¿Quieres recibir más artículos como este?
Suscríbete a nuestra newsletter: