La versión 4 de Symfony está fuertemente basada en el concepto de servicios. Todas las utilidades que proporciona el framework están configuradas como servicios que se pueden invocar desde cualquier módulo de la aplicación.
Por un lado están los servicios del núcleo de Symfony, como por ejemplo HttpKernel (que es el propio kernel de Symfony) o URLMatcher.
Cuando añades nuevos módulos a tu aplicación estos también registran sus servicios para que los tengas a tu disposición. Puedes ver todos los que tienes disponibles en tiempo real ejecutando esto desde la raíz de tu proyecto:
1 php bin/console debug:autowiring
Luego es muy fácil utilizarlos con la técnica de "type-hinting" que no es otra cosa que pasar el servicio como parámetro a la función desde donde quieras utilizarlo indicando su "tipo" (vamos, el nombre de la clase):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 /**
* @Route("/admin/item/crear", name="admin_item_add")
* @param CountryRepository $countryRepository
* @return Response
*
* Aquí se pasa un repositorio de paises a la función add de la clase Item
* Ese servicio permite solicitar el listado completo de la tabla
* de paises de la base de datos
*/
public function add(CountryRepository $countryRepository)
{
$countries = $countryRepository->findAll();
return $this->render('admin/item/item_add.html.twig', array(
"countries" => $countries));
}
Cuando desarrolles alguna funcionalidad en tu aplicación que pueda ser invocada desde distintas instancias, o que simplemente quieras desacoplar de la clase actual puedes implementarla como servicio. Este servicio no es más que una clase con una serie de métodos y que se coloca por convenio en la carpeta Service de la aplicación
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 <?php
/* /src/Service/DniGenerator.php */
namespace App\Service;
class DniGenerator
{
private static $crcMap = array('T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E', 'T');
public static function dni()
{
$number = static::randomNumber(8);
$letter = self::$crcMap[$number % 23];
return $number . $letter;
}
/**
* Devuelve un entero con $numberDigits digitos
* @param integer $numberDigits
* @example 79907610
* @return integer
*/
public static function randomNumber($numberDigits = 1)
{
$max = pow(10, $numberDigits) - 1;
if ($max > mt_getrandmax()) {
throw new \InvalidArgumentException('randomNumber() can only generate numbers up to mt_getrandmax()');
}
return mt_rand(pow(10, $numberDigits - 1), $max);
}
}
Ahora sólo necesitas invocar el servicio desde donde lo necesites. En este ejemplo lo vas a llamar desde un controlador que carga la página de inicio de una aplicación web mínima. Todo el secreto está en el parámetro y en el tipo que se le pasa al método donde vas a utilizar el servicio function index(DniGenerator $dniGenerator) El famoso "Type-Hinting".
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 <?php
/* /src/Controller/HomeController.php */
namespace App\Controller;
use App\Service\DniGenerator;
use Symfony\Component\HttpFoundation\Response;
class HomeController
{
/**
* @param DniGenerator $dniGenerator
* @return Response
*/
public function index(DniGenerator $dniGenerator)
{
$dni = $dniGenerator->dni();
return new Response(
'<html><body><h1>Generador aleatorio de DNI</h1><h2>DNI: '.$dni.'</h2></body></html>'
);
}
}
Para que todo esto funcione correcta y mágicamente es importante que el fichero de configuración de servicios esté bien configurado (por defecto ya viene así por lo que no tendrás que tocar nada). Aquí tienes el fichero de configuración de servicios:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 # config/services.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'
# ...
Por último lanza el servidor web de PHP para desarrollo desde un terminal con la orden
1 php -S 127.0.0.1:8000 -t public
Y luego accede en el navegador a la dirección http://127.0.0.1:8000 Recarga la página para ir obteniendo nuevos DNIs aleatorios y válidos.
Bueno, espero que te haya gustado la explicación y que te ha quedado clara la idea. En cualquier caso tienes todo el código en Github por si quieres hacer pruebas. No olvides hacer composer update tras descargarlo.