Cómo utilizar la herencia de paquetes para redefinir partes de un paquete

Cuando trabajes con paquetes de terceros, probablemente llegues a una situación en la que desees reemplazar un archivo en ese paquete de terceros con un archivo de uno de tus propios paquetes. Symfony te proporciona una forma muy conveniente para sustituir cosas como controladores, plantillas, traducciones, y otros archivos en el directorio Resources/ de los paquetes.

Por ejemplo, supongamos que estás instalando el FOSUserBundle, pero deseas sustituir su plantilla base —layout.html.twig—, así como uno de sus controladores. Supongamos también que tienes tu propio AcmeUserBundle donde deseas que vivan los archivos sobrescritos. Para empezar, registra el FOSUserBundle como el «padre» de tu paquete:

// src/Acme/UserBundle/AcmeUserBundle.php
namespace Acme\UserBundle;

    use Symfony\Component\HttpKernel\Bundle\Bundle;

class AcmeUserBundle extends Bundle
{
    public function getParent()
    {
        return 'FOSUserBundle';
    }
}

Al hacer este simple cambio, ahora puedes sustituir varias partes del FOSUserBundle simplemente creando un archivo con el mismo nombre.

Nota

A pesar del nombre del método, entre paquetes no hay una relación padre/hijo, sólo es una manera de extender y reemplazar un paquete existente.

Sustituyendo controladores

Supongamos que deseas añadir alguna funcionalidad al RegisterAction de RegistrationController que vive dentro de FOSUserBundle. Para ello, basta con crear tu propio archivo RegistrationController.php, reemplaza el método original, y cambia su funcionalidad:

// src/Acme/UserBundle/Controller/RegistrationController.php
namespace Acme\UserBundle\Controller;

    use FOS\UserBundle\Controller\RegistrationController as BaseController;

class RegistrationController extends BaseController
{
    public function registerAction()
    {
        $response = parent::registerAction();

        // ... haz tus cosas personalizadas
        return $response;
    }
}

Truco

Dependiendo de cuanto necesites cambiar el comportamiento, puedes llamar a parent::RegisterAction() o sustituir por completo su lógica con la tuya.

Nota

La sustitución de controladores de esta forma solo funciona si el paquete se refiere al controlador usando la sintaxis estándar FOSUserBundle:Registration:register en las rutas y plantillas. Esta es la buena práctica.

Sustituyendo recursos: Plantillas, Enrutado, Validación, etc.

También puedes cambiar la mayoría de los recursos, simplemente creando un archivo en la misma ubicación que en el padre de tu paquete.

Por ejemplo, es muy común que necesites reemplazar la plantilla layout.html.twig de FOSUserBundle para que utilice el diseño base de tu aplicación. Debido a que el archivo vive en Resources/views/layout.html.twig en FOSUserBundle, puedes crear tu propio archivo en el mismo lugar dentro de AcmeUserBundle. Symfony ignorará el archivo que vive dentro de FOSUserBundle por completo, y en su lugar utilizará ese archivo.

Lo mismo ocurre con los archivos de enrutado, la configuración de validación y otros recursos.

Nota

La sustitución de recursos sólo funciona cuando haces referencia a los recursos con el método @FosUserBundle/Resources/config/routing/security.xml. Si te refieres a recursos sin utilizar el acceso directo @BundleName, no puedes reemplazar en esta forma.

Prudencia

Los archivos de traducción no funcionan de la misma manera como se describió anteriormente. todos los archivos de traducción se acumulan en un conjunto de «piscinas» (una por cada) dominio. Symfony, primero carga los archivos de traducción desde los paquetes (en el orden en que se inician los paquetes) y luego desde tu directorio app(Resources. Si la misma traducción se especifica en dos recursos, gana la traducción de los recursos cargada al último.

Bifúrcame en GitHub