Un bundle es básicamente una carpeta que contiene los archivos necesarios para un grupo de funcionalidades específicas, un concepto similar al de los plugins en otras aplicaciones, como por ejemplo un blog, un carrito de compras o hasta el mismo frontend y backend de nuestra aplicación. La diferencia clave es que en Symfony 2 (Sf2) todo es un bundle, incluyendo tanto la funcionalidad básica de la plataforma como el código escrito para tu aplicación, de tal forma que esta vez les quiero mostrar como hacer Crear Bundles en Symfony.

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.

Las aplicaciones Sf2 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

En este artículo te enseñaremos  crear bundles en Sf2

Comencemos

1.- Crear el bundle

La distribucion estandar de Sf2 cuenta un comando completamente funcional para crear tus bundles, para mostrarte lo sencillo que es crearemos un bundle llamado “PonceelrelajadoDemoBundle”

$ php app/console generate:bundle --namespace=Ponceelrelajado/DemoBundle --format=yml

Sin que te des cuenta, se ha creado un directorio para el bundle en src/Ponceelrelajado/DemoBundle. Además se ha añadido automáticamente una línea en el archivo app/AppKernel.php para registrar el bundle en el núcleo de Symfony:

// app/AppKernel.php

public function registerBundles()

{

$bundles = array(

…,

new Ponceelrelajado\DemoBundle\PonceelrelajadoDemoBundle(),

);

// …

return $bundles;

}

Ahora que ya está configurado el bundle, puedes comenzar a construir tu aplicación dentro del bundle.

2.- Cambiar el enrutamiento

Por defecto, el archivo de configuración de enrutamiento en una aplicación Symfony2 se encuentra en app/config/routing.yml, pero, si quieres y al igual que en el resto de la configuración en Sf2, puedes utilizar el formato XML o PHP para configurar tus rutas.

Si te fijas en el archivo de enrutamiento principal, verás que Symfony ya ha agregado una entrada al generar el bundle “PonceelrelajadoDemoBundle”:

YAML

# app/config/routing.yml

acme_hello:
    resource: “@AcmeHelloBundle/Resources/config/routing.yml”
    prefix:   /

XML

<!– app/config/routing.xml –>

<?xml version=”1.0″ encoding=”UTF-8″ ?>

<routes xmlns=”http://symfony.com/schema/routing”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://symfony.com/schema/routing

http://symfony.com/schema/routing/routing-1.0.xsd”>

<import resource=”@AcmeHelloBundle/Resources/config/routing.xml”

prefix=”/” />

</routes>

PHP

// app/config/routing.php

use Symfony\Component\Routing\RouteCollection;

use Symfony\Component\Routing\Route;

$collection = new RouteCollection();

$collection->addCollection(

$loader->import(‘@AcmeHelloBundle/Resources/config/routing.php’),

‘/’

);

return $collection;

Básicamente le estamos diciendo a Symfony que cargue la configuración de enrutamiento del “archivo Resources/config/routing.yml” que se encuentra en el interior del bundle “PonceelrelajadoDemoBundle”.

En otras palabras, puedes configurar tus rutas directamente en el archivo app/config/routing.yml o puedes definirlas en varias partes de la aplicación y después las importas desde ese archivo.

Ahora que el archivo routing.yml del bundle se importa desde el archivo de enrutamiento principal de la aplicación, añade la nueva ruta que define la URL de la página que estás a punto de crear:

YAML

# src/Ponceelrelajado/DemoBundle/Resources/config/routing.yml

hello:
    path:     /hello/{name}
    defaults: { _controller: PonceelrelajadoDemoBundle:Hello:index }

XML

<!– src/Ponceelrelajado/DemoBundle/Resources/config/routing.xml –>

<?xml version=”1.0″ encoding=”UTF-8″ ?>

<routes xmlns=”http://symfony.com/schema/routing”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://symfony.com/schema/routing

http://symfony.com/schema/routing/routing-1.0.xsd”>

<route id=”hello” path=”/hello/{name}”>

<default key=”_controller”>PonceelrelajadoDemoBundle:Hello:index</default>

</route>

</routes>

PHP

// src/Ponceelrelajado/DemoBundle/Resources/config/routing.php

use Symfony\Component\Routing\RouteCollection;

use Symfony\Component\Routing\Route;

$collection = new RouteCollection();

$collection->add(‘hello’, new Route(‘/hello/{name}’, array(

‘_controller’ => PonceelrelajadoDemoBundle:Hello:index’,

)));

return $collection;

$collection = new RouteCollection();

$collection->addCollection(

$loader->import(‘@PonceelrelajadoDemoBundle/Resources/config/routing.php’),

‘/’

);

La ruta se compone básicamente de dos partes: el path, que es la URL con la que debe coincidir la petición del usuario para activar la ruta, y un array llamado defaults, que especifica el controlador que se ejecuta. Las partes de la URL encerradas entre comillas indican que su valor puede variar. De esta forma, {name} significa que las URL /hello/Ryan, /hello/Fabien o cualquier otra URI similar coincidirá con esta ruta. El valor de las partes variables también se pasa al controlador, que puede acceder a ellos a través del nombre asignado en la propia ruta (name en este caso).

3.- CONSTRUIR EL CONTROLADOR

Cuando el usuario solicita la URL /hello/Ryan, se activa la ruta hello, a la que corresponde el controlador PonceelrelajadoDemoBundle:Hello:index, qué es realmente el código que se ejecuta. El segundo paso del proceso de creación de páginas consiste precisamente en crear ese controlador.

La cadena PonceelrelajadoDemoBundle:Hello:index es el nombre lógico del controlador, que se traduce como el método indexAction() de una clase PHP llamada Ponceelrelajado\DemoBundle\Controller\Hello. Crea en primer lugar este archivo dentro de tu bundle “PonceelrelajadoDemoBundle”:

// src/Ponceelrelajado/DemoBundle/Controller/HelloController.php

namespace Ponceelrelajado\DemoBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController

{

}

En realidad, el controlador no es más que un método PHP que tú creas y Symfony ejecuta. Aquí es donde el código utiliza la información de la petición para construir y preparar el recurso solicitado. Salvo en algunos casos avanzados, el resultado final de un controlador siempre es el mismo: un objeto Response de Sf2.

Crea el método indexAction que Symfony ejecutará cuando se sirva la ruta hello:

// src/Ponceelrelajado/DemoBundle/Controller/HelloController.php

// …

class HelloController

{

public function indexAction($name)

{

return new Response(‘<html><body>Hello ‘.$name.’!</body></html>’);

}

}

El controlador es muy sencillo: crea un nuevo objeto de tipo Response y cuyo primer argumento es el contenido que se utiliza para crear la respuesta enviada al usuario (en este caso, una página HTML muy simple).

Después de crear solamente una ruta y un controlador ¡ya tienes una página completamente funcional! Si todo lo has configurado correctamente, la aplicación debe darte la bienvenida al acceder a la siguiente URL:

http://localhost/tu-directorio/web/app_dev.php/hello/Ponceelrelajado

Tambien puedes acceder a tu aplicacion en el entorno de produccion con la siguiente URL:

http://localhost/tu-directorio/web/app.php/hello/Ponceelrelajado

Pero antes debes limpiar el cache de tu aplicación, de lo contrario te mostrar un error:

php app/console cache:clear –env=prod –no-debug
4.- CONSTRUIR PLANTILLAS (OPCIONAL)

Las plantillas te permiten mover toda la parte de la vista (es decir, el código HTML) a un archivo separado y reutilizar diferentes partes del diseño de la página. En vez de escribir el código HTML dentro del controlador, genera el código HTML a partir de una plantilla:

// src/Ponceelrelajado/DemoBundle/Controller/HelloController.php

namespace Ponceelrelajado\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class HelloController extends Controller

{

public function indexAction($name)

{

return $this->render(‘PonceelrelajadoDemoBundle:Hello:index.html.twig’, array(‘name’ => $name));

// si utilizas PHP en vez de Twig

// return $this->render(‘PonceelrelajadoDemoBundle:Hello:index.html.php’, array(‘name’ => $name));

}

}

Para poder usar el método render(), tu controlador debe extender de la clase Symfony\Bundle\FrameworkBundle\Controller\Controller, de esta forma se añaden atajos para las tareas más comunes de los controladores. tal como se muestra en el ejemplo anterior.

Ten en cuenta que puedes procesar las plantillas de dos formas diferentes. Por defecto Sf2 admite dos lenguajes de plantillas: las clásicas plantillas creadas con PHP y las nuevas y concisas plantillas creadas con Twig. No te asustes porque puedes elegir libremente cuál utilizar o incluso mezclar las dos en el mismo proyecto.

Al procesar la plantilla “PonceelrelajadoDemoBundle:Hello:index.html.twig”, el controlador utiliza la siguiente convención de nomenclatura:

NombreBundle:NombreControlador:NombrePlantilla

Este es el nombre lógico de la plantilla, que se traduce a un archivo físico utilizando la siguiente convención:

</ruta/a/Nombrebundle>/Resources/views/<NombreControlador>/<NombrePlantilla>

En este caso, “PonceelrelajadoDemoBundle” es el nombre del bundle, “Hello” es el controlador e “index.html.twig” la plantilla:

index.html.twig

{# src/Ponceelrelajado/DemoBundle/Resources/views/Hello/index.html.twig #}

{% extends ‘::base.html.twig’ %}

{% block body %}

Hello {{ name }}!

{% endblock %}

index.html.php

<!– src/Ponceelrelajado/DemoBundle/Resources/views/Hello/index.html.php –>

<?php $view->extend(‘::base.html.php’) ?>

Hello <?php echo $view->escape($name) ?>!

Veamos la situación a través de la plantilla Twig línea por línea:

La etiqueta “extends” indica que se utiliza una plantilla padre donde se define el diseño del sitio web.

La etiqueta block indica que todo su contenido se debe colocar dentro de un bloque llamadobody. Como se explicará más adelante, la plantilla padre (base.html.twig) es la responsable de definir ese bloque y de mostrarlo en la página HTML adecuadamente.

La plantilla padre se indica como ::base.html.twig, por lo que no incluye ni la parte del nombre del bundle ni la del nombre del controlador (de ahí los dos puntos dobles (::) al principio). Esto significa que la plantilla no se encuentra dentro de ningún bundle, sino en el directorio app del proyecto:

base.html.twig

{# app/Resources/views/base.html.twig #}

<!DOCTYPE html>

<html>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

<title>{% block title %}Welcome!{% endblock %}</title>

{% block stylesheets %}{% endblock %}

<link rel=”shortcut icon” href=”{{ asset(‘favicon.ico’) }}” />

</head>

<body>

{% block body %}{% endblock %}

{% block javascripts %}{% endblock %}

</body>

</html>

base.html.php

<!– app/Resources/views/base.html.php –>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

<title><?php $view[‘slots’]->output(‘title’, ‘Welcome!’) ?></title>

<?php $view[‘slots’]->output(‘stylesheets’) ?>

<link rel=”shortcut icon” href=”<?php echo $view[‘assets’]->getUrl(‘favicon.ico’) ?>” />

</head>

<body>

<?php $view[‘slots’]->output(‘_content’) ?>

<?php $view[‘slots’]->output(‘stylesheets’) ?>

</body>

</html>

El archivo de la plantilla base define el diseño HTML y muestra el contenido del bloque body que se definió en la plantilla index.html.twig. También muestra el contenido de un bloque llamado title, que si quieres puedes definir en la plantilla index.html.twig. ¡Como no has definido ese bloque en la plantilla, se utiliza el valor predeterminado “Welcome!”.

Las plantillas son realmente útiles para generar y organizar el contenido de las páginas de la aplicación. Una plantilla puede generar cualquier cosa, desde el código HTML o CSS hasta cualquier otra cosa que el controlador tenga que devolver.

Dentro del ciclo petición/respuesta, el motor de plantillas simplemente es una herramienta opcional. Recuerda que el objetivo de cada controlador es devolver un objeto Response. Así que por muy potentes que sean, las plantillas son solo una forma opcional de generar ese objeto Response.

CONCLUSIÓN

En esta ocasión apreciamos la estructura principal de Symfony2, y creamos un bundle de ejemplo, aquí en Ponceelrelajado esperamos que este artículo te haya sido útil y que de ahora en adelante puedas desarrollar tus propios bundles y funcionalidades.

En venideros tutoriales ahondaremos en otros tips y herramientas prácticas de desarrollo web, tanto a nivel de back-end como front-end. ¡No olvides compartir este artículo en tus redes sociales si te gustó!