Curso de desarrollo de módulos con Drupal 7 (IX): Creación y gestión de Entidades (Parte I)

Como siempre crearemos un nuevo módulo pero esta vez definiremos una entidad que manejaremos desde Drupal. Este caso es un poco más complejo que el de la creación de un nuevo tipo de contenido, debido a que deberemos realizar todas las funcionalidades de gestión de información para esta nueva entidad.
Crearemos un carpeta para el módulo llamada “entity_example” y un nuevo fichero .info con el siguiente contenido:

; $Id: ajax_example.info,v 1.3 2010/08/11 23:16:27 rfay Exp $

name = Ejemplo de Entidad
description = Módulo de ejemplo que muestra como usar el API de Entidades de Drupal
core = 7.x
package = Modulos de ejemplo
files[] = entity_example.module
files[] = entity_example.install

Definiendo el Modelo de la BBDD

Como se vió en la tercera entrega es posible definir un esquema de bbdd para que nuestro módulo disponga de un conjunto de tablas y campos sobre los que manejar la información que necesita gestionar. Generamos un nuevo fichero entity_example.install, pero esta vez sólo tendremos la implementación de hook_squema():

<?php
// $Id$

/**
 * @file
 * Install/Update/Uninstall functions for entity_example module.
 */

/**
 * Implements hook_schema().
 *
 * @see hook_schema()
 * @link schemaapi Schema API @endlink
 */
function entity_example_schema() {
  $schema[‘example_entity’] = array(
    ‘description’ => ‘The base table for example entity’,
    ‘fields’ => array(
      ‘eeid’ => array(
        ‘description’ => ‘The primary identifier for a entity.’,
        ‘type’ => ‘serial’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
      ),
      ‘title’ => array(
        ‘description’ => ‘The title of this entity, always treated as non-markup plain text.’,
        ‘type’ => ‘varchar’,
        ‘length’ => 255,
        ‘not null’ => TRUE,
        ‘default’ => ”,
      ),
      ‘perm’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘size’ => ‘tiny’,
        ‘description’ => ‘Whether the example entity is permanent(1) or not(0).’,
      ),
      ‘dstart’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘Start date of example entity. Format: Ymd’,
      ),
      ‘dend’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘End date of example entity. Format: Ymd’,
      ),
      ‘weight’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘The weight of this example entity.’,
      ),
    ),
    ‘primary key’ => array(‘eeid’),
    ‘indexes’ => array(
      ‘perm’ => array(‘perm’),
      ‘dstart’ => array(‘dstart’),
      ‘dend’ => array(‘dend’),
    ),
  );
  return $schema;
}

Como podemos ver en modelo es sencillo:

  • Campos:
    • eeid: numero entero, sin signo, no puede ser null y clave primaria de la tabla
    • title: varchar de 255 caracteres que almacenará el título
    • perm: entero pequeño (tiny) que almacena valores 0 y 1
    • dstart y dend: fecha inicio y fin 
    • weigth: peso de la entidad.
  • Clave primaria: campo eeid
  • indices:
    • perm
    • dstart
    • dend

Hasta aquí el modelo está definido, cuando se active el módulo se generará la tabla ‘example_entity’ con las especificaciones que le hemos definido.

Añadir Permisos, hook_permission()

Ahora añadiremos el fichero .module donde colocaremos el resto del código del módulo.
Debido a que estamos manejando una nueva entidad será necesario aplicar nuevos permisos con el módulo para así poder controlar mejor que operaciones pueden realizar los usuarios. Para ello utilizaremos el hook_permission().  aquí tenemos un ejemplo de uso para el módulo:
/**
 * Implements hook_permission().
 */
function entity_example_permission() {
  return array(
    ‘administer example entity’ =>  array(
      ‘title’ => t(‘Administer example entity’),
      ‘restrict access’ => TRUE,
    ),
  );
}
Como puede verse el hook debe devolver un array asociativo con un elemento para cada nuevo permiso. En este caso es “administer example entity”, donde configuramos que su valor es otro array con el título (title) y si restrigiremos el acceso a la funcionalidad (restrict access), que en este caso lo haremos.

Definición de la entidad: hook_entity_info()

La definición de la entidad se realiza a través del hook_entity_info(), veamos un ejemplo de implementación para este módulo:
/**
 * Implementa hook_entity_info().
 */
function entity_example_entity_info() {
  $return = array(
    ‘entity_example’ => array(
      ‘label’ => t(‘Example entity’),
      ‘base table’ => ‘example_entity’,
      ‘uri callback’ => ‘entity_example_uri’,
      ‘fieldable’ => TRUE,
      ‘entity keys’ => array(
        ‘id’ => ‘eeid’,
      ),
      ‘bundles’ => array(
        ‘entity_example’ => array(
          ‘label’ => t(‘Example entity’),
          ‘admin’ => array(
            ‘path’ => ‘admin/structure/entity_example’,
            ‘access arguments’ => array(‘administer example entity’),
          ),
        ),
      ),
    ),
  );
  return $return;
}
Como puede verse se devuelve un array asociativo son los datos principales de las entidades que queremos definir. En este caso se está definiendo la entidad ‘entity_example’ como índice del array principal. Dentro del array que define cada entidad nos encontramos con los siguientes campos:

  • label: etiqueta principal
  • base_table: nombre de la tabla que gestiona la entidad
  • uri callback: nombre dela función que sabe manejar las URL’s de la entidad, nos permitirá pasar por URL la entidad que manejamos.
  • fieldable: booleano que define si la entidad es manejable mediante campos (Field API)
  • entity keys: array de claves primarias de la entidad, en este caso es el campo eeid
  • bundles: conjuntos de entidades que queremos gestionar, en este caso solo daremos una de alta correspondiendo a la entidad que hemos dado de alta ‘entity_example’
    • nombre_entidad: aqui referenciamos el bundle con la entidad
      • label: etiqueta de la entidad para el bundle
      • admin: array con los datos de la administración del bundle para la entidad
        • path: rura de acceso a la administración
        • access arguments: array de permisos necesarios para la gestión de la entidad

A continuación debemos programar la función que permite manejar las rutas de la entidad para Drupal:
/**
 * Entity uri callback.
 */
function entity_example_uri($entity_example) {
  return array(
    ‘path’ => ‘entity_example/’ . $entity_example->eeid,
  );
}
Como puede verse nos pasan la entidad entera y devolvemos el path con el ID de la entidad que nos pasan en el campo “path” concatenado con la rura principal “entity_example/”.
Tambiñen deberemos sobreescribir el hook_admin_paths(), para que funcionen correctamente las rutas de edición de entidades:
/**
 * Implements hook_admin_paths().
 */
function entity_example_admin_paths() {
  $paths = array(
    ‘entity_example/*/edit’ => TRUE,
  );
  return $paths;
}
 De esta manera cambiaremos algunos paths administrativos del módulo, en concreto el que tiene que ver con la edición de elementos de la entidad.
Esto se entenderá mucho mejor cuando veamos los enlaces generados con el hook_menu().

Entradas del menú para hacer el CRUD

Como se ha mencionado anteriormente será necesario dar de alta todas las funcionalidades de la gestión de la nueva entidad y sus enlaces en el menú, como siempre, lo haremos a través del hook_menu():

/**
 * Implements hook_menu().
 */
function entity_example_menu() {
  $items[‘entity_example/%entity_example’] = array(
    ‘title’ => ‘Example entity’,
    ‘title callback’ => ‘entity_example_page_title’,
    ‘title arguments’ => array(1),
    ‘page callback’ => ‘entity_example_page’,
    ‘page arguments’ => array(1),
    ‘access arguments’ => array(‘access content’),
    ‘type’ => MENU_CALLBACK,
  );
  $items[‘entity_example/%entity_example/view’] = array(
    ‘title’ => ‘View’,
    ‘type’ => MENU_DEFAULT_LOCAL_TASK,
  );
  $items[‘entity_example/%entity_example/edit’] = array(
    ‘title’ => ‘Edit’,
    ‘page callback’ => ‘drupal_get_form’,
    ‘page arguments’ => array(‘entity_example_form_edit’, 1),
    ‘access arguments’ => array(‘administer example entity’),
    ‘type’ => MENU_LOCAL_TASK,
    ‘weight’ => 10,
  );

  $items[‘admin/structure/entity_example’] = array(
    ‘title’ => ‘Example entities’,
    ‘description’ => ‘Manage example entities on your site.’,
    ‘access arguments’ => array(‘administer example entity’),
    ‘page callback’ => ‘entity_example_page_admin’,
    ‘page arguments’ => array(‘list’),
    ‘weight’ => -10,
  );

  $items[‘admin/structure/entity_example/list’] = array(
    ‘title’ => ‘List’,
    ‘type’ => MENU_DEFAULT_LOCAL_TASK,
    ‘weight’ => -10,
  );

  $items[‘admin/structure/entity_example/create’] = array(
    ‘title’ => ‘Add example entity’,
    ‘page arguments’ => array(‘create’),
    ‘access arguments’ => array(‘administer example entity’),
    ‘type’ => MENU_LOCAL_ACTION,
  );

  return $items;
}

Como podemos ver estamos gestionando muchos enlaces, así que explicaremos uno a uno su significado para entender mejor su funcionamiento, en la siguiente entrega.

Referencias:

Licencia Creative Commons

Curso de Symfony 2 (III): del modelo de la BBDD al Controlador CRUD Básico

Una vez configurada la aplicación tal como se indicaba en la parte II, donde disponíamos ya de una base de datos llamada s2 y nuestra aplicación estaba configurada para funcionar con dicha base de datos, a través del fichero de configuración app/config/parameters.ini:
[parameters]
    database_driver=”pdo_mysql”
    database_host=”localhost”
    database_port=””
    database_name=”s2″
    database_user=”root”
    database_password=””
    mailer_transport=”smtp”
    mailer_host=”localhost”
    mailer_user=””
    mailer_password=””
    locale=”es”
    secret=”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
Será necesario crear un nuevo Bundle para poder ir introduciendo nuestro código en la aplicación.
Para ello deberemos ejecutar un comando en terminal de comandos llamando al php.exe, sí éste se ha incluido en el Path del sistema, podremos ejecutarlso simplemente escribiendo “php” en la línea de comandos, si no es así deberemos escribir la ruta completa al fichero php.exe desde el directorio de instalación de xampp, en el caso de la instalación por defecto sería “C:xamppphpphp.exe”.
Todos los comandos deberán ser ejecutados en el directorio de instalación de Symfony2.
El comando que debemos ejecutar para crear el Bundle es:

php app/console generate:bundle --namespace=Pepesan/NuevoBundle --format=yml 

He aquí una captura de la consola de Aptana (mi gestor de proyectos y editor de ficheros PHP), ejecutando el comando de consola…

aunque también podemos ejecutar todos los comandos desde el intérprete de comandos de Windows, como en esta captura…

Como puede observase en el comando:

  • Primero se llama al php.exe, sin poner la extensión, es el intérprete que vamso a utilizar para ejecutar el comando, en el ejemplo “php”
  • Después indicamos que queremos utilizar la consola de aplicaciones de symfony2, en el ejemplo “app/console”.
  • Después indicamos el comando en concreto que queremos ejecutar, la generación de un nuevo bundle, en el ejemplo “generate:bundle”.
  • Después indicamos el espacio de nombres del nuevo bundle, exactamente donde se va a guardar, indicando la ruta a partir del directorio src, en el ejemplo “–namespace=Pepesan/NuevoBundle”.
  • Después indicamos el formato que queremos utilizar para la configuración, en este caso YAML, en el ejemplo “–format=yml”

A continuación, veremos la salida del comando que acabamos de ejecutar,  donde el comando se verá la información y las preguntas que nos va haciendo y las contestaciones que debemos ir dando para seguir el ejemplo. Pondré en Itálica, la información que presenta el comando por sí mismo y en negrita lo que hago para continuar el comando:
 Welcome to the Symfony2 bundle generator

Your application code must be written in bundles. This command helps
you generate them easily.

Each bundle is hosted under a namespace (like Acme/Bundle/BlogBundle).
The namespace should begin with a “vendor” name like your company name, your
project name, or your client name, followed by one or more optional category
sub-namespaces, and it should end with the bundle name itself
(which must have Bundle as a suffix).

See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#index-1
for more
details on bundle naming conventions.

Use / instead of for the namespace delimiter to avoid any problem.

Bundle namespace [Pepesan/NuevoBundle]: aquí pulso la tecla “enter”, porque me sirve ese espacio de nombres para el Bundle.

In your code, a bundle is often referenced by its name. It can be the
concatenation of all namespace parts but it’s really up to you to come
up with a unique name (a good practice is to start with the vendor name).
Based on the namespace, we suggest PepesanNuevoBundle.

Bundle name [PepesanNuevoBundle]: aqui vuelvo a pulsar la tecla “enter”, porque me sirve ese nombre para referenciar al Bundle, este nombre lo suaremos cuando queramos referenciar elementos de este Bundle en el código.

The bundle can be generated anywhere. The suggested default directory uses
the standard conventions.

Target directory [C:xampphtdocsSymfony/src]: Simplemente pulso la tecla “enter”, porque el directorio src me sirve para guardar las carpetas y ficheros del bundle.

Determine the format to use for the generated configuration.

Configuration format (yml, xml, php, or annotation) [yml]: vuelvo a pulsar “enter”, porque quiero usar el formato YAML para la configuración.

To help you getting started faster, the command can generate some
code snippets for you.

Do you want to generate the whole directory structure [no]? yes (pulso enter, despues de escribir “yes”, para aceptar que me genere el arbol completo de directorios del bundle)

  Summary before generation

You are going to generate a “PepesanNuevoBundlePepesanNuevoBundle” bundle
in “C:xampphtdocsSymfony/src/” using the “yml” format.

Do you confirm generation [yes]? aqui vuelvo a pulsar la tecla “enter”, para aceptar las configuraciones que me han resumido

  Bundle generation

Generating the bundle code: OK
Checking that the bundle is autoloaded: OK
Confirm automatic update of your Kernel [yes]?
pulso “enter”, porque quiero que me añada el Bundle automáticamente al kernel de mi apliciación, fichero “app/AppKernel.php”.
Enabling the bundle inside the Kernel: OK
Confirm automatic update of the Routing [yes]?
pulso “enter”, porque quiero que me incluya las rutas definidas en el Bundle en la aplicación, en el fichero “app/config/routing.yml”
Importing the bundle routing resource: OK

  You can now start using the generated code!

Una vez que terminamos de ejecutar el comando veremos que efectivamente me han creado, dentro del directorio “src” un directorio llamado “Pepesan” y dentro de ese directorio uno llamado “Nuevo Bundle”, que contendrá la esctructura del nuevo Bundle, similar a la que se muestra en la captura…

Como puede observarse con la ejecución del comando nos ha creado la estructura completa del Bundle:

  • Controller/ contiene los controladores de Bundle (p.e. NuevoController.php)
  • DependencyInjection/ contendrá el código de injección de pendencias del bundle
  • Resources/config/ guarda la configuración, incluyendo las rutas del bundle (p.e. routing.yml)
  • Resources/views/ almacena las plantillas de vista del bundle (p.e. Nuevo/index.html.twig)
  • Resources/public/ contiene los elementos de la web (imágenes, css, etc…) que será copiados o enlazados simbólicamente al directorio “web” mediante el comando “assets:install"
  • Tests/ almacena las pruebas del bundle

También si vemos el fichero “app/config/routing.yml”, veremos que nos ha incluido las siguientes líneas:
PepesanNuevoBundle:
    resource: “@PepesanNuevoBundle/Resources/config/routing.yml”
    prefix:   /

Y que nos ha modificado el fichero “app/AppKernel.php” pra incluir una línea en la carga de bundles:
$bundles = array(
            new SymfonyBundleFrameworkBundleFrameworkBundle(),
            new SymfonyBundleSecurityBundleSecurityBundle(),
            new SymfonyBundleTwigBundleTwigBundle(),
            new SymfonyBundleMonologBundleMonologBundle(),
            new SymfonyBundleSwiftmailerBundleSwiftmailerBundle(),
            new SymfonyBundleDoctrineBundleDoctrineBundle(),
            new SymfonyBundleAsseticBundleAsseticBundle(),
            new JMSSecurityExtraBundleJMSSecurityExtraBundle(),
            new AcmeDemoBundleAcmeDemoBundle(),
            new PepesanNuevoBundlePepesanNuevoBundle(),
        );

Con estas configuraciones ya tendremos el nuevo Bundle creado y configurada la aplicación para hacer uso del nuevo Bundle.

 

Importando el modelo en la base de datos

Para poder trabajar con datos en fundamental definirlos, digamos por ejemplo en la base de datos. Para empezar vamos a trabajar con una estructura sencilla, sólo una tabla en la base de datos. Para ello, usaremos el siguiente fichero de volcado de base de datos SQL…


— Estructura de tabla para la tabla `clientes`

CREATE TABLE IF NOT EXISTS `clientes` (
  `clienteid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nombre` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `tlf` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `web` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `dir` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`clienteid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci AUTO_INCREMENT=9 ;


— Volcado de datos para la tabla `clientes`

INSERT INTO `clientes` (`clienteid`, `nombre`, `tlf`, `web`, `image`, `dir`) VALUES
(1, ‘pepe’, ‘656661477’, ‘http://www.plexxoo.com’, ‘http://images.wikia.com/lotr/es/images/5/59/Eomer.jpg’, ‘calle de mi casa’),
(3, ‘pepe3’, ‘656661479’, ‘http://www.plexxoo.com’, ‘http://images.wikia.com/lotr/es/images/5/59/Eomer.jpg’, ‘calle de mi casa3’),
(4, ‘pepe3’, ‘656661479’, ‘http://www.plexxoo.com’, ‘http://images.wikia.com/lotr/es/images/5/59/Eomer.jpg’, ‘calle de mi casa3’),
(5, ‘pepe3’, ‘656661479’, ‘http://www.plexxoo.com’, ‘http://images.wikia.com/lotr/es/images/5/59/Eomer.jpg’, ‘calle de mi casa3’),
(7, ‘pepe’, ‘pp’, ‘pp’, ‘pp’, ‘pp’),
(8, ‘www’, ‘www’, ‘www’, ‘www’, ‘ww’);

Para importar este modelo, será necesario abrir el phpmyadmin, mediante la URL: http://localhost/phpmyadmin
veremos una pantalla similar a la siguiente…

pulsaremos sobre el enlace de la parte irzquierda de la pantalla, llamado como la base de datos que hemos creado “s2“, así veremos a estructura de la base de datos…

Pulsaremos sobre el botón SQL, para poder introducir el código SQL de generación de la tabla “clientes”…

pulsaremos en el botón “Continuar”, si todo ha ido bien, no debería sacar ningún mensaje de error y al pulsar sobre el botón “Estructura”, deberíamos poder ver la tabla en el listado, tal como aparece en la siguiente captura…

Al terminar este paso, ya dispondremos de una tabla con datos iniciales en la base de datos contra la que está configurada la aplicación de Symfony2.

Importando el modelo de la base de datos con Doctrine

Una vez que disponemos de un modelo ya en la base de datos, será necesario importarlo para generar los ficheros de Entidad de Doctrine para así disponer de una manera de consultar y manejar la tabla de la base de datos con el Bundle de nuestra aplicación Symfony2.
Para ello tenemos que seguir una serie de pasos:

  1. Generar un fichero de configuración XML, teniendo como modelo las tablas de la base de datos.
  2. Generar las entidades en base a ese modelo XML.
  3. Usar esas entidades en los controladores del bundle.

Para generar el fichero XML de configuración debemos ejecutar otro comando de Symfony2:

php app/console doctrine:mapping:convert xml ./src/Pepesan/NuevoBundle/Resources/config/doctrine/metadata/orm --from-database --force

Como puede observase en el comando:

  • Primero se llama al php.exe, sin poner la extensión, es el intérprete que vamso a utilizar para ejecutar el comando, en el ejemplo “php”
  • Después indicamos que queremos utilizar la consola de aplicaciones de symfony2, en el ejemplo “app/console”.
  • Después indicamos el comando en concreto que queremos ejecutar, la generación de un nuevo fichero de mapping (relación entre campos de la base de datos y atributos de los objetos de Doctrine), en el ejemplo “doctrine:mapping:convert”
  • Después indicamos el formato que queremos utilizar para el fichero, en el ejemplo “xml”
  • Después indicamos donde queremos guardar el fichero, en el ejemplo “./src/Pepesan/NuevoBundle/Resources/config/doctrine/metadata/orm”
  • Después indicamos desde donde queremos coger la información que vamos a guardar en el XML, en ejemplo “–from-database”
  • Por último indicamos que queremos que fuerce la generación sobreescribiendo lo que sea necesario, en el ejemplo “–force”

 Si todo ha ido correctamente deberíamos ver una salida similar a la que aparece en la captura…

como resultado nos sacará el mensaje…
Processing entity “Clientes”

Exporting “xml” mapping information to “C:xampphtdocsSymfonysrcPepesanNuevoBundleRes
ourcesconfigdoctrinemetadataorm”

Y dispondremos de un cambio en la estructura del bundle, nos habrá creado un nuevo fichero en el directorio “PepesanNuevoBundleResourcesconfigdoctrinemetadataorm” llamado “clientes.orm.xml” que tendrá el contenido del mapping de la base de datos…
<?xml version=”1.0″ encoding=”utf-8″?>
<doctrine-mapping xmlns=”http://doctrine-project.org/schemas/orm/doctrine-mapping” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd”>
  <entity name=”Clientes” table=”clientes”>
    <change-tracking-policy>DEFERRED_IMPLICIT</change-tracking-policy>
    <id name=”clienteid” type=”integer” column=”clienteid”>
      <generator strategy=”IDENTITY”/>
    </id>
    <field name=”nombre” type=”string” column=”nombre” length=”50″/>
    <field name=”tlf” type=”string” column=”tlf” length=”20″/>
    <field name=”web” type=”string” column=”web” length=”255″/>
    <field name=”image” type=”string” column=”image” length=”255″/>
    <field name=”dir” type=”string” column=”dir” length=”255″/>
    <lifecycle-callbacks/>
  </entity>
</doctrine-mapping>

Como puede verse en el fichero, se establece una relación o mapping, entre la tabla “clientes”  y la Entidad “Clientes”, relacionando todos los atributos de la nueva Entidad con los campos de la tabla.

Generando las Entidades

Ahora deberemos importar este XML para generar los ficheros de Clases Entidad, para ello deberemos ejecutar dos comandos.
El primero es el siguiente:

php app/console doctrine:mapping:import PepesanNuevoBundle annotation

Como puede observase en el comando:

  • Primero se llama al php.exe, sin poner la extensión, es el intérprete que vamso a utilizar para ejecutar el comando, en el ejemplo “php”
  • Después indicamos que queremos utilizar la consola de aplicaciones de symfony2, en el ejemplo “app/console”.
  • Después indicamos el comando en concreto que queremos ejecutar, la importación en el bundle del fichero de mapping XML, en ejemplo “doctrine:mapping:import”
  • Después indicamos el bundle donde queremos importar el fichero, en el ejemplo “PepesanNuevoBundle”
  • Por último, indicamos cómo queremos manejar el mapping, en este caso como anotaciones en el código, en el ejemplo “annotations”

 Así tendremos una salida similar a la de la captura…

donde nos informa de que ha generado correctamente el fichero de Entidad “Clientes.php”…
Importing mapping information from “default” entity manager
  > writing C:xampphtdocsSymfonysrcPepesanNuevoBundle/Entity/Clientes.php
Dicho fichero se coloca en el directorio “Entity” de nueva creación en el directorio del Bundle, si miramos su contenido veremos lo siguiente…
<?php

namespace PepesanNuevoBundleEntity;

use DoctrineORMMapping as ORM;

/**
 * PepesanNuevoBundleEntityClientes
 *
 * @ORMTable(name=”clientes”)
 * @ORMEntity
 */
class Clientes
{
    /**
     * @var integer $clienteid
     *
     * @ORMColumn(name=”clienteid”, type=”integer”, nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy=”IDENTITY”)
     */
    private $clienteid;

    /**
     * @var string $nombre
     *
     * @ORMColumn(name=”nombre”, type=”string”, length=50, nullable=false)
     */
    private $nombre;

    /**
     * @var string $tlf
     *
     * @ORMColumn(name=”tlf”, type=”string”, length=20, nullable=false)
     */
    private $tlf;

    /**
     * @var string $web
     *
     * @ORMColumn(name=”web”, type=”string”, length=255, nullable=false)
     */
    private $web;

    /**
     * @var string $image
     *
     * @ORMColumn(name=”image”, type=”string”, length=255, nullable=false)
     */
    private $image;

    /**
     * @var string $dir
     *
     * @ORMColumn(name=”dir”, type=”string”, length=255, nullable=false)
     */
    private $dir;

}

Si observamos el fichero generado con un poco más de calma, nos fijamos en las dos inclusiones de código:

  • El namespace, con la localización del fichero en el Bundle.
  • El Use con la inclusión de la biblioteca de ORM-Mapping de Doctrine, de esta manera disponemos de unos comentarios similares al uso de las entidades JPA de J2EE, pero en Symfony2
  • El código comentado indicando la relación de la entidad con la tabla
  • El nombre de la clase como el nombre de la tabla, salvo porque la primera letra es mayúscula
  • Y luego indicando atributo a atributo, su relación con los nombres de campos de la tabla y sus validaciones, con especial atención a la clave primaria de tabla, que actua como identificativo único de la entidad.

Después de esto ejecutamos el último comando:
php app/console doctrine:generate:entities PepesanNuevoBundle
Como puede observase en el comando:

  • Primero se llama al php.exe, sin poner la extensión, es el intérprete que vamso a utilizar para ejecutar el comando, en el ejemplo “php”
  • Después indicamos que queremos utilizar la consola de aplicaciones de symfony2, en el ejemplo “app/console”.
  • Después indicamos el comando en concreto que queremos ejecutar, generación de las entidades y su puesta en marcha, en ejemplo “doctrine:generate:entities”
  • Después indicamos el bundle donde queremos generar las entidades, en el ejemplo “PepesanNuevoBundle”

Tal como se puede ver en la siguiente captura…

 la salida nos indica lo siguiente…
Generating entities for bundle “PepesanNuevoBundle”
  > backing up Clientes.php to Clientes.php~
  > generating PepesanNuevoBundleEntityClientes

Nos hace un backup del fichero Clientes.php y nos sobre escribe el fochero Clientes.php con el siguiente contenido…
<?php

namespace PepesanNuevoBundleEntity;

use DoctrineORMMapping as ORM;

/**
 * PepesanNuevoBundleEntityClientes
 *
 * @ORMTable(name=”clientes”)
 * @ORMEntity
 */
class Clientes
{
    /**
     * @var integer $clienteid
     *
     * @ORMColumn(name=”clienteid”, type=”integer”, nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy=”IDENTITY”)
     */
    private $clienteid;

    /**
     * @var string $nombre
     *
     * @ORMColumn(name=”nombre”, type=”string”, length=50, nullable=false)
     */
    private $nombre;

    /**
     * @var string $tlf
     *
     * @ORMColumn(name=”tlf”, type=”string”, length=20, nullable=false)
     */
    private $tlf;

    /**
     * @var string $web
     *
     * @ORMColumn(name=”web”, type=”string”, length=255, nullable=false)
     */
    private $web;

    /**
     * @var string $image
     *
     * @ORMColumn(name=”image”, type=”string”, length=255, nullable=false)
     */
    private $image;

    /**
     * @var string $dir
     *
     * @ORMColumn(name=”dir”, type=”string”, length=255, nullable=false)
     */
    private $dir;

    /**
     * Get clienteid
     *
     * @return integer
     */
    public function getClienteid()
    {
        return $this->clienteid;
    }

    /**
     * Set nombre
     *
     * @param string $nombre
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;
    }

    /**
     * Get nombre
     *
     * @return string
     */
    public function getNombre()
    {
        return $this->nombre;
    }

    /**
     * Set tlf
     *
     * @param string $tlf
     */
    public function setTlf($tlf)
    {
        $this->tlf = $tlf;
    }

    /**
     * Get tlf
     *
     * @return string
     */
    public function getTlf()
    {
        return $this->tlf;
    }

    /**
     * Set web
     *
     * @param string $web
     */
    public function setWeb($web)
    {
        $this->web = $web;
    }

    /**
     * Get web
     *
     * @return string
     */
    public function getWeb()
    {
        return $this->web;
    }

    /**
     * Set image
     *
     * @param string $image
     */
    public function setImage($image)
    {
        $this->image = $image;
    }

    /**
     * Get image
     *
     * @return string
     */
    public function getImage()
    {
        return $this->image;
    }

    /**
     * Set dir
     *
     * @param string $dir
     */
    public function setDir($dir)
    {
        $this->dir = $dir;
    }

    /**
     * Get dir
     *
     * @return string
     */
    public function getDir()
    {
        return $this->dir;
    }
}
De esta manera nos incluye los método principales de manejo de los datos de la clase Clientes, denominados getter y setters.

Generando un CRUD básico desde una Entidad Doctrine

Una de las cuestiones principales la ahora de gestionar datos es la generación de las operaciones web de manejo de los datos.
La operaciones básicas del CRUD son:

  • Listar
  • Añadir
  • Mostrar
  • Editar
  • Borrar

Para ello utilizaremos la entidad “Clientes” como base de la generación de un Controlador CRUD web.
Para que funcione correctamente la generación será necesario modificar el fichero Clientes.php para que el atributo de la clave primaria de llame “$id” en vez de “$clientesid” de la siguiente manera…
/**
     * @var integer $id
     *
     * @ORMColumn(name=”clienteid”, type=”integer”, nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy=”IDENTITY”)
     */
    private $id;

También será necesario cambiar el método getClientesid podniendo lo siguiente:
/**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
Como puede observarse lo único que se han cambiado son los comentarios que están colocados antes de la definición del atributo, el nombre del propio atributo, el método de obtención de datos del atributo $id, todo lo demás en el fichero permanecerá constante.
A continucación ejecutaremos el comando:
php app/console generate:doctrine:crud –entity=PepesanNuevoBundle:Clientes –format=yml
 –with-write

Como puede observase en el comando:

  • Primero se llama al php.exe, sin poner la extensión, es el intérprete que vamso a utilizar para ejecutar el comando, en el ejemplo “php”
  • Después indicamos que queremos utilizar la consola de aplicaciones de symfony2, en el ejemplo “app/console”.
  • Después indicamos el comando en concreto que queremos ejecutar, generación un CRUD a través de las entidades doctrine, en ejemplo “generate:doctrine:crud”
  •  Después indicamos el nombre de la entidad en base a la cual queremos generar el CRUD, en el ejemplo “–entity=PepesanNuevoBundle:Clientes”
  • Por último indicamos el formato de las rutas de URL que queremos utilizar, en este caso YAML, en el ejemplo, “–format=yml”

Con este ocmando dispondremos también de una salida compleja, en itálica veremos la salida estándar y en negrita las pulsaciones de teclado…
 Welcome to the Doctrine2 CRUD generator

This command helps you generate CRUD controllers and templates.

First, you need to give the entity for which you want to generate a CRUD.
You can give an entity that does not exist yet and the wizard will help
you defining it.

You must use the shortcut notation like AcmeBlogBundle:Post.

The Entity shortcut name [PepesanNuevoBundle:Clientes]: Pulsamos “Enter”

By default, the generator creates two actions: list and show.
You can also ask it to generate “write” actions: new, update, and delete.

Do you want to generate the “write” actions [yes]?Pulsamos “Enter”

Determine the format to use for the generated CRUD.

Configuration format (yml, xml, php, or annotation) [yml]:Pulsamos “Enter”

Determine the routes prefix (all the routes will be “mounted” under this
prefix: /prefix/, /prefix/new, …).

Routes prefix [/clientes]:Pulsamos “Enter”


  Summary before generation

You are going to generate a CRUD controller for “PepesanNuevoBundle:Clientes”
using the “yml” format.

Do you confirm generation [yes]?Pulsamos “Enter”

  CRUD generation

Generating the CRUD code: OK
Generating the Form code: OK
Confirm automatic update of the Routing [yes]?
no ( y pulsamos “Enter”)
Importing the CRUD routes: FAILED

  The command was not able to configure everything automatically.
  You must do the following changes manually.

– Import the bundle’s routing resource in the bundle routing file
  (C:xampphtdocsSymfonysrcPepesanNuevoBundle/Resources/config/routing.yml).

    PepesanNuevoBundle_clientes:
        resource: “@PepesanNuevoBundle/Resources/config/routing/clientes.yml”
        prefix:   /clientes

Como nos indica la salida no se ha podido configurar automaticamente las rutas, pero nos dice la solución al problema, includir el fichero de rutas del bundle desde la configuración de la rutas de la aplicación De esta manera copiaremos el código:
    PepesanNuevoBundle_clientes:
        resource: “@PepesanNuevoBundle/Resources/config/routing/clientes.yml”
        prefix:   /clientes

y lo pegaremos al final del fichero app/config/routing.yml.
De esta manera incluimos la condifuración de rutas del bundle en la aplicación por que al entrar en la URL: http://localhost/s2/web/app_dev.php/clientes deberíamos ver una pantalla similar a la siguiente…

En la siguiente entrega veremos cómo funciona el código generado y cómo empezar a modificar los comportamientos web por defecto del CRUD.



Referencias:

Suscríbete al Boletín

Si quieres estar al tanto de las novedades del blog, ya sabes :)
* = campo obligatorio

powered by MailChimp!

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. ACEPTAR

Aviso de cookies