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

Sitio alternativo a Cuevana: Moviezet

Sitio alternativo a Cuevana: Moviezet : Nadie se quiere enfrentar al monstruo Cuevana , tan popular por estos días que es casi imposible ver tu serie favorita o tu película sin tener problema de saturación de tráfico. Pero hay proyectos muy sanos y prometedores, sobre todo porque están basados como una muy buena alternativa . Señores estamos hablando obviamente de un sitio alternativo a Cuevana, llamado Moviezet. Como bien dijimos, Moviezet es una excelente alternativa a Cuevana, ya que podremos ver películas y series de forma gratuita sin necesidad de que existan cortes – al mejor estilo Megavideo – y que podremos tener un seguimiento, es decir, si miramos una serie, podremos ver toda la lista con los capítulos disponibles. Lo que tiene de novedoso este sitio web Moviezet , es que tiene películas y series que quizá en Cuevana no se puedan conseguir, pero atención, que puede suceder lo mismo, pero al revés. Entonces aquí intervenimos nosotros y te daremos un sabio consejo, para no

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