Symfony 2.3, el libro oficial

4.4. El sistema de bundles

Un bundle es un concepto similar al de los plugins en otras aplicaciones, pero todavía mejor. La diferencia clave es que en Symfony2 todo es un bundle, incluyendo tanto la funcionalidad básica de la plataforma como el código escrito para tu aplicación.

Los bundles son la parte más importante de Symfony2. Permiten utilizar funcionalidades construidas por terceros o empaquetar tus propias funcionalidades para distribuirlas y reutilizarlas en otros proyectos. Además, facilitan mucho la activación o desactivación de determinadas características dentro de una aplicación.

Nota En esta sección solo se va a explicar lo básico, pero hay un capítulo dedicado completamente al tema de los bundles.

Un bundle simplemente es un conjunto estructurado de archivos que se encuentran en un directorio y que implementan una sola característica. Puedes crear por ejemplo un BlogBundle, un ForoBundle o un bundle para gestionar usuarios (muchos de ellos ya existen como bundles de software libre). Cada directorio contiene todo lo relacionado con esa característica, incluyendo archivos PHP, plantillas, hojas de estilo, archivos Javascript, tests y cualquier otra cosa necesaria.

Las aplicaciones Symfony se componen de bundles, tal como se define en el método registerBundles() de la clase AppKernel:

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
        new Symfony\Bundle\SecurityBundle\SecurityBundle(),
        new Symfony\Bundle\TwigBundle\TwigBundle(),
        new Symfony\Bundle\MonologBundle\MonologBundle(),
        new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
        new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
        new Symfony\Bundle\AsseticBundle\AsseticBundle(),
        new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
    );

    if (in_array($this->getEnvironment(), array('dev', 'test'))) {
        $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
        $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
        $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
        $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
    }

    return $bundles;
}

Con el método registerBundles(), puedes controlar completamente los bundles que utiliza tu aplicación, incluso aquellos bundles que forman el núcleo del framework.

Truco Un bundle se puede encontrar en cualquier directorio, siempre y cuando Symfony2 lo pueda cargar automáticamente (con el autocargador configurado en app/autoload.php).

4.4.1. Creando un bundle

La edición estándar de Symfony incluye un comando para crear bundles totalmente funcionales de una manera muy sencilla. Por supuesto, también puedes crear los bundles a mano si lo prefieres.

Para mostrarte lo sencillo que es el sistema de bundles, vamos a crear a mano y activar un nuevo bundle llamado AcmeTestBundle.

Truco La parte Acme es sólo un nombre ficticio que debes sustituir por el nombre del proveedor del bundle, es decir, el nombre o siglas de tu empresa (por ejemplo, ABCTestBundle si la empresa se llama ABC). Si es un bundle personal, puedes utilizar tu nombre completo o las iniciales.

En primer lugar, crea un directorio src/Acme/TestBundle/ y añade un nuevo archivo llamado AcmeTestBundle.php::

// src/Acme/TestBundle/AcmeTestBundle.php
namespace Acme\TestBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class AcmeTestBundle extends Bundle
{
}

Truco El nombre AcmeTestBundle sigue las convenciones estándar de nomenclatura de bundles. También puedes optar por acortar el nombre del bundle simplemente a TestBundle al nombrar esta clase TestBundle (y el nombre del archivo TestBundle.php).

Esta clase vacía es lo único que necesitamos para crear nuestro nuevo bundle. Aunque normalmente está vacía, esta clase te permite personalizar el comportamiento del bundle.

Ahora que hemos creado nuestro bundle, tenemos que activarlo a través de la clase AppKernel:

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        ...,

        // registra tus bundles
        new Acme\TestBundle\AcmeTestBundle(),
    );
    // ...

    return $bundles;
}

Aunque todavía no hace nada, el bundle AcmeTestBundle ya está listo para utilizarlo.

Generar un bundle a mano es bastante sencillo, pero Symfony también proporciona un comando para generar la estructura básica del bundle:

php app/console generate:bundle --namespace=Acme/TestBundle

Como resultado este comando genera el esqueleto del bundle formado por un controlador básico, la plantilla y la configuración del enrutamiento. Más adelante se explica en detalle la consola de comandos de Symfony2.

Truco Cuando crees un nuevo bundle o uses un bundle de terceros, asegúrate siempre de habilitar el bundle en el método registerBundles(). El comando generate:bundle se encarga de hacerlo automáticamente.

4.4.2. Estructura de directorios de un bundle

La estructura de directorios de un bundle es simple y flexible. Por defecto el sistema de bundles sigue una serie de convenciones que ayudan a mantener el código consistente entre todos los bundles Symfony2. Echa un vistazo a AcmeHelloBundle, ya que contiene algunos de los elementos más comunes de un bundle:

  • Controller/: contiene los controladores del bundle (por ejemplo, HelloController.php).
  • DependencyInjection/: contiene elementos relacionados con el contenedor de inyección de dependencias, un concepto muy avanzado que se explicará más adelante. Entre otras, contiene las extensiones para las clases de inyección de dependencias, la configuración que importan los servicios y registra uno o más pases del compilador (este directorio no es obligatorio).
  • Resources/config/: contiene la configuración, incluyendo la configuración de enrutamiento (por ejemplo, routing.yml).
  • Resources/views/: contiene las plantillas organizadas según el nombre del controlador (por ejemplo, Hello/index.html.twig).
  • Resources/public/: contiene recursos web (imágenes, hojas de estilo, etc.) y es copiado o enlazado simbólicamente al directorio web/ del proyecto con el comando assets:install.
  • Tests/: tiene los tests unitarios y funcionales del bundle.

Un bundle puede ser tan pequeño o tan grande como sea necesario.

A medida que avances en el libro, aprenderás cómo persistir objetos a una base de datos, crear y validar formularios, crear traducciones para tu aplicación, escribir tests y mucho más. Cada uno de estos tiene su propio lugar y rol dentro del bundle.