Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

¡Los controladores también son servicios!

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Abre src/Controller/VinylController.php. ¡Puede que sea obvio o no, pero nuestras clases de controlador también son servicios en el contenedor! ¡Sí! Se sienten especiales porque son controladores... pero en realidad sólo son viejos y aburridos servicios como todo lo demás. Bueno, excepto que tienen un superpoder que no tiene nada más: la capacidad de autoconectar argumentos en sus métodos de acción. Normalmente, el autocableado sólo funciona con el constructor.

Vinculación de los argumentos de la acción

Los métodos de acción funcionan realmente como los constructores en lo que respecta a la autoconexión. Por ejemplo, añade un argumento bool $isDebug a la acción browse()... y a continuación dump($isDebug):

... lines 1 - 6
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
... lines 9 - 13
class MixRepository
{
... lines 16 - 24
public function findAll(): array
{
$output = new BufferedOutput();
$this->twigDebugCommand->run(new ArrayInput([]), $output);
dd($output);
... lines 30 - 35
}
}

Y eso... ¡no funciona! Hasta ahora, las únicas dos cosas que sabemos que podemos tener como argumentos de nuestras "acciones" son (A), cualquier comodín en la ruta como$slug y (B) los servicios autocableables, como MixRepository.

Pero ahora, vuelve a config/services.yaml y descomenta el global bind de antes:

... lines 1 - 12
services:
# default configuration for services in *this* file
_defaults:
... lines 16 - 17
bind:
'bool $isDebug': '%kernel.debug%'
... lines 20 - 32

Esta vez... ¡funciona!

Añadir un constructor

Yendo en la otra dirección, como los controladores son servicios, puedes absolutamente tener un constructor si quieres. Movamos MixRepository y $isDebug a un nuevo constructor. Cópialos, quítalos... añade public function __construct(), pégalos... y luego los pondré en sus propias líneas. Para convertirlos en propiedades, añadeprivate delante de cada uno:

... lines 1 - 10
class VinylController extends AbstractController
{
public function __construct(
private bool $isDebug,
private MixRepository $mixRepository
)
{}
... lines 18 - 36
#[Route('/browse/{slug}', name: 'app_browse')]
public function browse(string $slug = null): Response
{
... lines 40 - 48
}
}

De nuevo abajo, sólo tenemos que asegurarnos de cambiar a dump($this->isDebug) y añadir $this-> delante de mixRepository:

... lines 1 - 10
class VinylController extends AbstractController
{
public function __construct(
private bool $isDebug,
private MixRepository $mixRepository
)
{}
... lines 18 - 36
#[Route('/browse/{slug}', name: 'app_browse')]
public function browse(string $slug = null): Response
{
dump($this->isDebug);
... lines 41 - 42
$mixes = $this->mixRepository->findAll();
... lines 44 - 48
}
}

¡Bien! Si probamos esto ahora... ¡funciona bien!

Normalmente no sigo este enfoque... principalmente porque añadir argumentos al método de acción es muy fácil. Pero si necesitas un servicio u otro valor en cada método de acción de tu clase, definitivamente puedes limpiar tu lista de argumentos inyectándola a través del constructor. Voy a eliminar ese dump().

A continuación, vamos a hablar de las variables de entorno y de la finalidad del archivo .env que hemos visto antes. Estas cosas serán cada vez más importantes a medida que hagamos nuestra aplicación más y más realista.

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "knplabs/knp-time-bundle": "^1.18", // v1.19.0
        "symfony/asset": "6.1.*", // v6.1.0-RC1
        "symfony/console": "6.1.*", // v6.1.0-RC1
        "symfony/dotenv": "6.1.*", // v6.1.0-RC1
        "symfony/flex": "^2", // v2.1.8
        "symfony/framework-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/http-client": "6.1.*", // v6.1.0-RC1
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/runtime": "6.1.*", // v6.1.0-RC1
        "symfony/twig-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/ux-turbo": "^2.0", // v2.1.1
        "symfony/webpack-encore-bundle": "^1.13", // v1.14.1
        "symfony/yaml": "6.1.*", // v6.1.0-RC1
        "twig/extra-bundle": "^2.12|^3.0", // v3.4.0
        "twig/twig": "^2.12|^3.0" // v3.4.0
    },
    "require-dev": {
        "symfony/debug-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/maker-bundle": "^1.41", // v1.42.0
        "symfony/stopwatch": "6.1.*", // v6.1.0-RC1
        "symfony/web-profiler-bundle": "6.1.*" // v6.1.0-RC1
    }
}