El curso estará estructura por un conjunto de artículos que abarcaran los aspectos básicos a conocer para desarrollar entidades en drupal 7. Este desarrollo estará basado en un ejemplo práctico que ayudara a salir de un ambiente conceptual y adentrarnos en un caso particular.
Primera parte
Conocimientos previos para entender este tutorial:
PHP, Desarrollo en drupa, POO, Base de datos relacionales.
Nota: Este tutorial enfocará solo los aspectos dirigidos a entity api, no se explicará nada relacionado al desarrollo común de módulos de drupal, se toma como consenso que ya es un conocimiento previamente tomado.
Objetivo del curso
Aprender mediante un ejemplo práctico como desarrollar entidades en drupal7.
Subjetivos:
- Como crear entidades en drupal 7.
- Gestión entre entidades.
Introducción:
El curso estará estructura por un conjunto de artículos que abarcarán los aspectos básicos a conocer para desarrollar entidades en drupal 7. Este desarrollo estará basado en un ejemplo práctico que ayudara a salir de un ambiente conceptual y adentrarnos en un caso particular.
Caso práctico:
Se pretende desarrollar un módulo para drupal 7 que permita llevar las estadísticas de campeonatos de fútbol, donde se gestionen los torneos, jornadas y partidos por jornadas, así como toda la gestión de equipos que participen en cada uno de los torneo.
Un torneo se conforma por varias jornadas y varios equipos, una jornada por muchos partidos y estos a su vez por 2 equipos.
Se debe llevar una tabla de resultados donde se reporten la cantidad de juegos jugados, juegos perdidos, juegos empatados y ganados, así como la cantidad de goles a favor y en contra y el total de puntos acumulados por cada equipo participante en el torneo.
Desarrollo Tema 1:
Nota: Se tomará la entidad torne como base para explicar todo el contenido del código mostrado.
Puntos a tratar:
- Extraer las entidades del caso práctico.
- Implementación del hook_schema.
- Implementación del hook_entity_info.
- Implementación de nuestros EntityController.
Desarrollo:
Extraer las entidades del caso práctico.
/* Implements hook_schema(). * */ function module_name_schema() { //--------------------MODULE_NAME_TORNEO---------------------- 'unsigned' => TRUE, //auto incrementado el campo 'type' => 'serial', // se define el tipo de dato 'not null' => TRUE, //Si puede o no ser nudo este valor ), 'type' => 'int', // se define el tipo de dato 'default' => 0, //se define valor por defecto ), 'type' => 'int', 'default' => 0, ), 'type' => 'varchar', 'length' => '100', //se asigna un tamaño del campo 'default' => '', ), ), 'torneo_id' ), ); //Continuamos con las otras entidades de la misma forma que //anteriormente se explicó... return $schema; }
Implementación del hook_entity_info:
function module_name_entity_info() { //------------------------------module_name_torneo------------------------------------------- //Etiqueta para identificar la entidad. 'label' => t('module_name_torneo'), //Controlador que maneja los métodos de la entidad, por defecto es // EntityAPIController. 'controller class' => 'Entitymodule_name_torneoController', //Definimos la tabla relacionada en el hook_schema() que manejará esta //entidad. 'base table' => 'module_name_torneo', //Define la función que retornara la entidad en cuestión 'uri callback' => 'module_name_torneo_uri', //Se le da la posibilidad a la entidad de agregar nuevos campos, como hace las //entity node,user... 'fieldable' => TRUE, //Identificador de la entidad, llave que se definió en el hook_schema() para esta entidad. 'id' => 'torneo_id' ,//llave de la tabla ), //Así definimos un bundle para agrupar entidades de un mismo //tipo o que represente herencias, y quede de una forma organizada. //ejemplo es Content Type que agrupa a artículos, paginas básicas... //Etiqueta del bundle 'label' => 'module_name_torneo bundle', //Datos administrativos de la entidad //Definimos la dirección desde donde se administrara la entidad. 'path' => 'admin/structure/module_name_torneo/manage', //Permiso que se debe tener para poder gestionar esta entidad, //este permiso debe de ser declarado previamente en el hook__permission() del módulo en cuestión. ), ), ), //Se definen los modos de vistas para distintos contexto donde participe esta entidad, se puede relacionar con el modulo view. 'label' => t('Tweaky'), 'custom settings' => FALSE, ), ) ); //Se debe continuar con la implementación de las 3 entidades restantes de la misma manera que implementada esta. return $info; }
Implementación de nuestros EntityController:
El EntityController conforma la capa de negocio de la entidad, es donde se definen nuevos métodos o redefinen otros a nuestra conveniencia, esta clase es a la que hace referencia el hook_entity_info anteriormente explicado 'controller class' => 'Entitymodule_name_torneoController', cuando se solicite un método de una de las entidades serán buscados en este controlador y luego ejecutado. EntityAPIController ya implementa por defecto los métodos principales save,delete,update,load. Si se utiliza EntityAPIController en el en el hook_entity_info ('controller class' => EntityAPIController) no será necesario implementar un nuevo controlador, solo si necesitamos realizar operaciones especifica en nuestra entidad.
Conclución:
Hasta aquí la primera parte de este curso, entre los aspectos tratados en esta primera parte, se destaca la creación de entidades,implementación de EntityController e integración con el hook_schema() y hook_entity_info, en próximos capítulos veremos la integración con los módulos y la gestión de los field, las vistas y el manejo entre entidades a través del EntityContoller implementado en esta primera parte.
//Se crea esta interfaz porque cualquiera puede alterar la entidad con el hook ¬¬//hook_entity_info_alter(). Aquí se da a saber que métodos necesita la clase //para que interactúe con el resto del módulo. interface Entitymodule_name_torneoControllerInterface extends DrupalEntityControllerInterface { public function create(); public function save($entity); public function delete($entity); } //Esta clase permite implementar los nuevos métodos no heredados de ¬¬//DrupalDefaultEntityController y re implementar los de la interface //anteriormente explicada a su conveniencia. class Entitymodule_name_torneoController extends DrupalDefaultEntityController implements Entitymodule_name_torneoControllerInterface { //Se crea una nueva entidad y se definen los vlores por defecto de la misma. public function create() { $entity = new stdClass(); $entity->type = 'module_name_torneo'; $entity->bundle_type = 'module_name_torneo'; $entity->torneo_id=0; $entity->categoria_id=0; $entity->estado=0; $entity->nombre=''; return $entity; } //Este método es el encargado de guardar o actualizar la entidad en caso que ya exista. public function save($entity) { //Se invoca el hook_entity_presave() de entity api. module_invoke_all('entity_presave', $entity, 'module_name_torneo'); //Se toman las llaves de la entidad, en caso de que ya exista la entidad y se //quiera actualizar en caso de ser una nueva entidad se retorna un array vacío. //Se escribe el registro de la entidad. drupal_write_record('module_name_torneo', $entity, $primary_keys); //se define la variable invocation con valor de inserción por defecto. $invocation = 'entity_insert'; //verificando si la entidad existe o es nueva, si es nueva existira al ¬¬menos una //llave en el array $primary_keys (llave primaria definida en el //hook_entity_info()) . //insertando los nuevos campos adicionados a la entidad (como la entidad no contien llaves, se inserta como nueva) field_attach_insert('module_name_torneo', $entity); } else { //Si contiene alguna llave es que ya la entidad existe y lo que debe hacer es actualizarse los nuevos campos. field_attach_update('module_name_torneo', $entity); //Se cambia el valor de la variable del insert anteriormente asignado a update. $invocation = 'entity_update'; } //Se invoca el hook 'entity_update o 'entity_insert' en dependencia del valor //que traiga en el campo llave de la entidad. module_invoke_all($invocation, $entity, 'module_name_torneo'); return $entity; } //Metodo eliminar de la entidad public function delete($entity) { //Se invoca el metodo delete_multiple posteriormente explicado. } //Este método elimina 1 o varias entidades en dependencia de lo que se envié //en el array $entities pasado como parámetro. public function delete_multiple($entities) { //Se crea una transaction $transaction = db_transaction(); try { //Se recorre el array de entidades y se invoca el hook 'entity_delete' de la //entity API y se eliminan los campos añadidos a la entidad. foreach ($entities as $entity) { module_invoke_all('entity_delete', $entity, 'module_name_torneo'); field_attach_delete('module_name_torneo', $entity); //Se guarda cada uno de los ids o llaves de la entidad que se eliminará. $torneo_ids[] = $entity->torneo_id; } //Se eliminan los registros de la tabla module_name_torneo que tengan en su campo de llave primaria alguno de los ids del array , $torneo_ids. db_delete('module_name_torneo') ->condition('torneo_id', $torneo_ids, 'IN') ->execute(); } catch (Exception $e) { //Se reinvierte el proseso si ocurrio un problema en la ejecución. $transaction->rollback(); watchdog_exception('torneo_id', $e); throw $e; } } } // Aquí podemos definir tantos métodos como necesitemos en nuestra entidad }
Anexo:
Si no quedo muy claro la explicación de la integración entre hook_schema, hook_entity_info y EntityController, se le muestra una imagen donde se refleja la integración entre los mismo.
Se refleja la relación entre Schema,entity_info y contoladores, el hoock_entity_info integra todo ,¨base table¨ integra el schema con la entidad,y ¨controller class¨ integra los controladores que la gestionarán, y estos a su vez implementan todos los metodos de la misma.