This course is still being released! Check back later for more chapters.

Get Notified About this Course!

We will send you messages regarding this course only
and nothing else, we promise.
You can unsubscribe anytime by emailing us at:
privacy@symfonycasts.com
Login to bookmark this video
Buy Access to Course
04.

Clase de servicio bundle

|

Share this awesome video!

|

Keep on Learning!

Bien, nuestro bundle está instalado y listo para funcionar. Es hora de añadir algo de funcionalidad añadiendo nuestra primera clase de servicio. Ésta será la estrella del espectáculo. Nuestro bundle es para traducir objetos, así que éste parece el lugar adecuado para empezar.

En el directorio src de nuestro bundle, crea una nueva clase PHP: ObjectTranslator.

ObjectTranslator

En primer lugar, marca esta clase como final. No está pensada para ser ampliada. Al desarrollar bundles, es importante ser explícito sobre el diseño de tus clases y sus intenciones. Esto facilita mantener la compatibilidad hacia atrás. Eliminar finalmás adelante no es un cambio de ruptura, pero añadir final sí lo es. Exploraremos más trucos de este tipo a medida que avancemos:

// ... lines 1 - 4
final class ObjectTranslator
{
// ... lines 7 - 17
}

Crear un método: public function translate(object $object). Tipo de retorno: object. Con el tiempo, albergará la lógica para traducir objetos. Por ahora, sólo devuelve el$object pasado:

// ... lines 1 - 4
final class ObjectTranslator
{
// ... lines 7 - 13
public function translate(object $object): object
{
return $object;
}
}

Nuestro servicio necesita un constructor para inyectar algunas cosas. Añade public function __construct(private LocaleAwareInterface $localeAware, private string $defaultLocale). Necesitamos el servicio LocaleAwareInterface para obtener la configuración regional actual de la petición, y también necesitaremos la configuración regional por defecto de nuestra aplicación:

// ... lines 1 - 6
final class ObjectTranslator
{
public function __construct(
private LocaleAwareInterface $localeAware,
private string $defaultLocale,
) {
}
// ... lines 14 - 33
}

Abajo, en translate(), podemos añadir algo de lógica sencilla. Obtén la configuración regional actual con$locale = $this->localeAware->getLocale(). Ahora bien, si la configuración regional actual es la misma que la configuración regional por defecto, no necesitamos hacer ninguna traducción, así que añade un if ($this->defaultLocale === $locale) y, en este caso, sólo devuelve el objeto sin procesar:

// ... lines 1 - 6
final class ObjectTranslator
{
// ... lines 9 - 21
public function translate(object $object): object
{
$locale = $this->localeAware->getLocale();
if ($this->defaultLocale === $locale) {
return $object;
}
// ... lines 29 - 32
}
}

A continuación es donde añadiremos la lógica de traducción real, pero de momento añade un comentario: todo translate object:

// ... lines 1 - 6
final class ObjectTranslator
{
// ... lines 9 - 21
public function translate(object $object): object
{
// ... lines 24 - 29
// todo translate object
return $object;
}
}

Utilicemos este nuevo servicio en ArticleController::show(). Amplía un poco este método e inyéctalo: ObjectTranslator $translator:

38 lines | src/Controller/ArticleController.php
// ... lines 1 - 11
final class ArticleController extends AbstractController
{
// ... lines 14 - 22
#[Route('/news/{slug:article}', name: 'app_article_show')]
public function show(Article $article, ObjectTranslator $translator): Response
// ... lines 25 - 36
}

Ejecuta el Article inyectado a través de nuestro nuevo servicio:$article = $translator->translate($article):

38 lines | src/Controller/ArticleController.php
// ... lines 1 - 11
final class ArticleController extends AbstractController
{
// ... lines 14 - 23
public function show(Article $article, ObjectTranslator $translator): Response
{
$article = $translator->translate($article);
// ... lines 27 - 35
}
}

¡Genial!

Genéricos PHP

Observa que si intentamos acceder a un método de $article antes de ejecutarlo a través de nuestro servicio, PhpStorm puede autocompletar todos los métodos de $article. Pero... si intentamos acceder a un método en $article después de ejecutarlo a través de$translator->translate(), no tenemos autocompletado. PhpStorm no tiene ni idea de qué es ahora $article - sólo que es "un objeto". Esto es un fastidio... ¡Pero podemos arreglarlo con los genéricos de PHP!

Los genéricos son una forma de proporcionar información de tipo adicional a nuestro editor.

Fíjate en esto: encima de ObjectTranslator::translate(), genera algunos bloques doc. Esto sólo coincide con la firma del método y no es superútil... así que añade@template T of object encima. Esto declara un tipo de plantilla T que debe ser un objeto. T es como un alias, o marcador de posición y puede ser cualquier cadena.

Ahora, para @param y @return, sustituye object por T:

// ... lines 1 - 6
final class ObjectTranslator
{
// ... lines 9 - 14
/**
* @template T of object
*
* @param T $object
*
* @return T
*/
public function translate(object $object): object
// ... lines 23 - 33
}

Esto le dice a nuestro editor: "Sea cual sea el tipo de objeto que se pase a este método, el tipo devuelto será el mismo tipo de objeto"

De vuelta en ArticleController::show(), después de llamar a translate(), intenta autocompletar de nuevo en $article. ¡Pum! Ahora PhpStorm sabe exactamente qué es $article. ¡Esto me encanta!

Elimina ese código extra - el artículo traducido se pasa ahora a nuestra plantilla, así que nuestro trabajo aquí está hecho.

Volvemos a nuestro navegador y visitamos la página del artículo... Un error... "No se puede autohilar el argumento $translator..."

Symfony no conoce el servicio de nuestro bundle - sigue siendo una simple clase PHP...

¡Arreglémoslo a continuación!