Passa al contingut principal

Curso Symfony 2: Instalando Bundles de Terceros

Curso Symfony 2: Instalando Bundles de Terceros:

En reiteradas ocaciones existe la necesidad de implementar librerías de terceros en nuestros proyectos con el objetivo primordial de aprovecharlas, reutilizar código y mejorar nuestros tiempos de entrega; como ya saben en Symfony 2 todo se distribuye en forma de “Bundles” y las librerías de terceros no son la excepción, además en symfony2bundles.org (actualmente http://knpbundles.com/) podrás encontrar miles de bundles que podrías necesitar.

En este capítulo nos concentraremos en la instalación de uno de los Bundles más atractivos para incluir en nuestros proyectos, se trata del StofDoctrineExtensionsBundle por Christophe Coevoet el cual hace una implementación del complemento Doctrine2 behavioral extensions creado por Gediminas Morkevicius, cuyo propósito es proveer de los aclamados Comportamientos (behaviors) de Doctrine; en general explicaremos la configuración de 3 comportamientos ampliamente utilizados, como lo son Timestampable, Sluggable y Loggable, reiteramos que el objetivo del capítulo es la instalación de Bundles de Terceros en Symfony2 y no el de profundizar en todos los comportamientos que provee el StofDoctrineExtensionsBundle.

Paso 1: Instalando el Bundle

En Symfony 2 existen varias formas para la instalación de los bundles de terceros, entre ellas (y la más práctica) es la instalación por medio de submodule en GIT, si no sabes que es GIT te recomiendo visitar http://progit.org/book/es/ y tratar de instalarlo en tu sistema.

Comenzamos instalando la librería principal de Doctrine Behavioral Extensions, para ello accedemos a nuestra consola, nos ubicamos en la raíz del proyecto de symfony y ejecutamos:

~$ git submodule add git://github.com/l3pp4rd/DoctrineExtensions.git vendor/gedmo-doctrine-extensions

Nota

Si tienes problemas puedes descargar manualmente el paquete, sólo debes descomprimir su contenido y copiarlo al directorio /ruta_hacia_proyecto/vendor/gedmo-doctrine-extensions

Ahora si añadimos el StofDoctrineExtensionsBundle:

~$ git submodule add git://github.com/stof/StofDoctrineExtensionsBundle.git vendor/bundles/Stof/DoctrineExtensionsBundle

Nota

Si tienes problemas puedes descargar manualmente el paquete, sólo debes descomprimir su contenido y copiarlo al directorio /ruta_hacia_proyecto/vendor/bundles/Stof/DoctrineExtensionsBundle.

Registramos los Namespaces en nuestro app/autoload.php:

<?php

use Symfony\Component\ClassLoader\UniversalClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;

$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
    'Symfony'          => array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'),
    'Sensio'           => __DIR__.'/../vendor/bundles',
    'JMS'              => __DIR__.'/../vendor/bundles',
    'Doctrine\\Common' => __DIR__.'/../vendor/doctrine-common/lib',
    'Doctrine\\DBAL'   => __DIR__.'/../vendor/doctrine-dbal/lib',
    'Doctrine'         => __DIR__.'/../vendor/doctrine/lib',
    'Monolog'          => __DIR__.'/../vendor/monolog/src',
    'Assetic'          => __DIR__.'/../vendor/assetic/src',
    'Metadata'         => __DIR__.'/../vendor/metadata/src',
    // Aquí registramos:
    'Stof'  => __DIR__.'/../vendor/bundles',
    'Gedmo' => __DIR__.'/../vendor/gedmo-doctrine-extensions/lib',
));
// ... resto del archivo

Añadimos el Bundle a nuestro app/AppKernel.php:

<?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    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(),
            new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
            new MDW\BlogBundle\MDWBlogBundle(),
            new MDW\DemoBundle\MDWDemoBundle(),
            // Aquí Añadimos:
            new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
        );
// ... resto del archivo

Básicamente es todo lo que se realiza para incluir un Bundle.

Paso 2: Configurando el Bundle

En nuestro caso el StofDoctrineExtensionsBundle para funcionar requiere agregar configuración adicional al archivo app/config/config.yml de la aplicación (la mayoría de los bundles pueden detallar tales configuraciones en su documentación), para ello agregamos estos segmentos:

En la sección Doctrine Configuration, añadimos al final el mapping para StofDoctrineExtensions Bundle:

# Doctrine Configuration
doctrine:
    dbal:
        driver:   %database_driver%
        host:     %database_host%
        port:     %database_port%
        dbname:   %database_name%
        user:     %database_user%
        password: %database_password%
        charset:  UTF8

    orm:
        auto_generate_proxy_classes: %kernel.debug%
        auto_mapping: true
        # Añadimos el Mapping para StofDoctrineExtensionsBundle: -------------
        mappings:
            StofDoctrineExtensionsBundle: ~
# ... resto del archivo

Luego añadimos al final del mismo archivo la siguiente configuración:

# Añadimos las configuraciones específicas para el StofDoctrineExtensionsBundle
stof_doctrine_extensions:
    default_locale: en_US
    orm:
        default:
            sluggable: true
            timestampable: true
            loggable: true
            #demás behaviors para activar

Donde default: representa la configuración para todos los entornos, eso quiere decir que puedes añadir una configuración específica para cada entorno.

Paso 3: Utilizando los Comportamientos (Behaviors) en los modelos

En este tutorial nos concentraremos en los comportamientos sluggable, timestampable y loggable, para hacer las cosas más fáciles se recomienda añadir el siguiente Namespace a cada una de nuestras entidades en donde queramos añadir los comportamientos:

// añadimos luego del Namespace de la Entidad:
use Gedmo\Mapping\Annotation as Gedmo;

Algunos Behaviors como Loggable disponen de Entidades propias que requieren crearse en base de datos, para garantizar ello solo debemos ejecutar en consola el comando siguiente, de este modo Doctrine creará las tablas necesarias para almacenar los datos generados por los comportamientos que lo requieran:

~$ php app/console doctrine:schema:update --force

Sluggable: Permite que Doctrine cree automáticamente el “slug” o la típica cadena optimizada para buscadores utilizada comúnmente al indexar artículos de un blog. Para definir el slug debemos tener un campo destino que es donde se almacenará y uno o más campos origen (los Sluggable) de los cuales se construirá el slug y es tan simple como agregar los siguientes Metadatos a nuestros campos del modelo:

    // … dentro de una Entidad
    // Campo origen:
    /**
     * @var string $title
     *
     * @ORM\Column(name="title", type="string", length=255)
     * @Gedmo\Sluggable()
     */
    private $title;

    // … otras variables

    // Campo Destino:
    /**
     * @var string $slug
     *
     * @ORM\Column(name="slug", type="string", length=255)
     * @Gedmo\Slug(style="camel", separator="_", updatable=false, unique=true)
     */
    private $slug;
    // … dentro de una Entidad

Note que el campo desde donde se creará el slug ($title) tiene el Metadato @Gedmo\Sluggable(), de hecho puede definir más de uno. En cambio el campo de destino ($slug) tiene el Metadato @Gedmo\Slug(…) y por convención debe ser uno solo, los argumentos style, separator, updatable y unique son opcionales y se detallan en la documentación propia del autor, en este ejemplo se tiene una forma básica de configuración.

Cada vez que se cree un registro de la entidad, Doctrine automáticamente generará el slug y lo aplicará al campo destino, en el caso de modificaciones depende del valor del argumento updatable.

Timestampable: permite que Doctrine gestione la actualización del Timestamp en campos específicos al realizar operaciones de inserción y/o actualización. Para definir un campo con Timestampable solo debemos añadir el Metadato Gedmo\Timestampable(on=”action”), donde action puede ser created o updated respectivamente.

    // … dentro de una Entidad
    // Campo created:
    /**
     * @var date $created
     *
     * @ORM\Column(name="created", type="date")
     * @Gedmo\Timestampable(on="create")
     */
    private $created;
    // Campo updated:
    /**
     * @var datetime $updated
     *
     * @ORM\Column(name="updated", type="datetime")
     * @Gedmo\Timestampable(on="update")
     */
    private $updated;
    // … dentro de una Entidad

Doctrine automáticamente aplicará un nuevo Date al campo definido on=”create” al crear un nuevo registro de la entidad y actualizará el Timestamp del campo definido on=”update” al actualizar el registro de la entidad.

Loggable: permite que Doctrine lleve un control de Versiones sobre los campos indicados, permitiendo consultar las versiones y revertir hacia una versión anterior.

Para crear campos con log (control de versión) solo debemos añadir a cada campo el Metadato @Gedmo\Versioned(), además de añadir el Metadato @Gedmo\Loggable() a la Entidad correspondiente:

// ... encabezados del archivo
// definimos el Metadato @Gedmo\Loggable() a la Entidad:
/**
 * MDW\BlogBundle\Entity\Articles
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="MDW\BlogBundle\Entity\ArticlesRepository")
 * @Gedmo\Loggable()
 */
class Articles
{
    // … dentro de una Entidad
    // Campo $content será Versionable:
    /**
     * @var text $content
     *
     * @ORM\Column(name="content", type="text")
     * @Gedmo\Versioned()
     */
    private $content;
    // … demás contenido de la entidad

Doctrine automáticamente supervisará los updates hacia los atributos marcados como Versioned de  la entidad y llevará un control de versiones en la Entidad (Stof\DoctrineExtensionsBundle\Entity\LogEntry), y gracias al Repositorio de dicha entidad (\Gedmo\Loggable\Entity\Repository\LogEntryRepository) podremos consultar las Versiones e incluso Revertir los cambios (función $logRepositoryInstance->revert($Entity, $version);), aquí apreciamos un ejemplo de un controlador que lista los cambios:

    // Ejemplo dentro de un Controller:
    public function updateArticleAction($id) {
      $em = $this->getDoctrine()->getEntityManager();

      $article = $em->getRepository('MDWBlogBundle:Articles')->findOneBy(array('id' => $id));

      $article->setContent('editado');
      $em->persist($article);
      $em->flush();

      $content = '';
      // ver cambios
      $log = $em->getRepository('Stof\DoctrineExtensionsBundle\Entity\LogEntry');
      /* @var $log \Gedmo\Loggable\Entity\Repository\LogEntryRepository */

      $query_changues = $log->getLogEntriesQuery($article); //use $log->getLogEntries() para un result directo
      $changues = $query_changues->getResult();
      /* @var $version Stof\DoctrineExtensionsBundle\Entity\LogEntry */
      foreach ($changues as $version) {
        $fields = $version->getData();
        $content.= ' fecha: ' .
            $version->getLoggedAt()->format('d/m/Y H:i:s') .
            ' accion: "'  . $version->getAction() . '"'.
            ' usuario: "' . $version->getUsername() . '"'.
            ' objeto: "'  . $version->getObjectClass() . '"'.
            ' id: "'      . $version->getObjectId() . '"'.
            ' Version: "' . $version->getVersion() . '"'.
            ' datos:';
            foreach ($fields as $field => $value) {
              $content.= "-- " . $field . ': '. $value . '';
            }
      }
      // generamos una salida básica
      $r = new \Symfony\Component\HttpFoundation\Response();
      $r->setContent($content);
      return $r;
    }

De esta forma podemos aprovecharnos de algunos de los comportamientos más utilizados de Doctrine, reutilizar código y automatizar tareas en nuestros modelos.

Resumen Final

Como pudimos apreciar con Symfony2 disponemos de una amplia variedad de bundles de terceros a incluir para extender las capacidades de nuestras aplicaciones, aprovechar y reutilizar código mejorando considerablemente el tiempo en el desarrollo de nuestros proyectos; aprendimos que existen diversas formas de incluir nuestros bundles y que en dado caso podemos hacer instalaciones a mano, también de lo importante que es seguir la documentación de cada bundle para agregarlo en el Autoload o Kernel según corresponda y aplicar las configuraciones requeridas por el mismo.


Maycol Alvarez Maycol Alvarez para Maestros del Web.
Agrega tu comentario | Enlace permanente al artículo


Síguenos en: @maestros | Fan page

Comentaris

Entrades populars d'aquest blog

10 alternativas a Cuevana para ver películas online

10 alternativas a Cuevana para ver películas online : Durante este último tiempo, en Cuevana se sucedieron varios “problemas” por los cuales hubo que ajustar algunas cosas antes de tiempo (como el rediseño del sitio), que dejaron a algunos usuarios ciertos problemas para acceder a las películas o series del portal. Pero realmente esto es algo que no incumbe a los usuarios y, como sabemos, existen muchas otras alternativas a Cuevana dando vueltas por Internet, que intentaremos presentar aquí mismo. Los sitios que repasaremos funcionan del mismo modo que Cuevana, mediante la instalación de un plugin que permite visualizar los videos de Megaupload o WUShare, entre otros servicios, en una calidad de imágen realmente excelente. Tal como sucede con el más popular servicio, todos ellos tienen publicidad que en algunos casos resulta insoportable, pero como dice Federico en DotPod “a caballo regalado no se le miran los dientes”. Alternativas a Cuevana 1. Moviezet Posiblemente el mejor clon d...

Learn Composition from the Photography of Henri Cartier-Bresson

“Do you see it?” This question is a photographic mantra. Myron Barnstone , my mentor, repeats this question every day with the hopes that we do “see it.” This obvious question reminds me that even though I have seen Cartier-Bresson’s prints and read his books, there are major parts of his work which remain hidden from public view. Beneath the surface of perfectly timed snap shots is a design sensibility that is rarely challenged by contemporary photographers. Henri Cartier-Bresson. © Martine Franck Words To Know 1:1.5 Ratio: The 35mm negative measures 36mm x 24mm. Mathematically it can be reduced to a 3:2 ratio. Reduced even further it will be referred to as the 1:1.5 Ratio or the 1.5 Rectangle. Eyes: The frame of an image is created by two vertical lines and two horizontal lines. The intersection of these lines is called an eye. The four corners of a negative can be called the “eyes.” This is extremely important because the diagonals connecting these lines will form the breakdown ...

Más de 50 de las mejores herramientas online para profesores

No es una exageración afirmar que hay ciento de aplicaciones educativas por ahí por la red, para todos los gustos y de todos los colores, por lo que es difícil tratar de recogerlas todas en un listado. Sin embargo, algunas destacan más que otras por su innovación y por su capacidad para conseguir adeptos, y esas son las que protagonizan la presente recopilación. Son 50 interesantes herramientas online basadas en las recopilaciones de EduArea , las muchas ya tratadas en Wwwhat’s new y las destacadas por la experiencia. 1. Dropbox : Un disco duro virtual con varios GB gratuitos y al que se accede desde casi cualquier dispositivo. Sin embargo, es muchísimo más que eso, de hecho ya comentamos 20 razones . 2. Google Drive : La evolución de Google Docs que suma a sus múltiples herramientas de creación de documentos, un considerable espacio virtual gratuito. 3. CloudMagic : Una extensión y una app multidispositivo para buscar información simultáneamente en Gmail, Twitter, Facebook, Evernote ...