Curso de desarrollo de módulos para Drupal 7(III): hook_schema explicado con el módulo User

Para entender bien esta entrega será necesario tener conocimientos avanzados de uso de arrays en PHP.
Como explicar el hook_schema requiere de un modelo de datos en concreto vamos a apoyarnos sobre el módulo User, que forma parte del nucleo de Drupal.
Abrimos el fichero «modules/user/user.install» desde Aptana para ver su contenido, pulsando doble clic sobre él. Y nos encontramos con el siguiente código en la función user_schema():
/**
 * Implements hook_schema().
 */
function user_schema() {
  $schema[‘authmap’] = array(
    ‘description’ => ‘Stores distributed authentication mapping.’,
    ‘fields’ => array(
      ‘aid’ => array(
        ‘description’ => ‘Primary Key: Unique authmap ID.’,
        ‘type’ => ‘serial’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
      ),
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => «User’s {users}.uid.»,
      ),
      ‘authname’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 128,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => ‘Unique authentication name.’,
      ),
      ‘module’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 128,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => ‘Module which is controlling the authentication.’,
      ),
    ),
    ‘unique keys’ => array(
      ‘authname’ => array(‘authname’),
    ),
    ‘primary key’ => array(‘aid’),
    ‘foreign keys’ => array(
      ‘user’ => array(
        ‘table’ => ‘users’,
        ‘columns’ => array(‘uid’ => ‘uid’),
      ),
    ),
  );

  $schema[‘role_permission’] = array(
    ‘description’ => ‘Stores the permissions assigned to user roles.’,
    ‘fields’ => array(
      ‘rid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Foreign Key: {role}.rid.’,
      ),
      ‘permission’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 128,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => ‘A single permission granted to the role identified by rid.’,
      ),
      ‘module’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 255,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => «The module declaring the permission.»,
      ),
    ),
    ‘primary key’ => array(‘rid’, ‘permission’),
    ‘indexes’ => array(
      ‘permission’ => array(‘permission’),
    ),
    ‘foreign keys’ => array(
      ‘role’ => array(
        ‘table’ => ‘roles’,
        ‘columns’ => array(‘rid’ => ‘rid’),
      ),
    ),
  );

  $schema[‘role’] = array(
    ‘description’ => ‘Stores user roles.’,
    ‘fields’ => array(
      ‘rid’ => array(
        ‘type’ => ‘serial’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique role ID.’,
      ),
      ‘name’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 64,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => ‘Unique role name.’,
        ‘translatable’ => TRUE,
      ),
      ‘weight’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘The weight of this role in listings and the user interface.’,
      ),
    ),
    ‘unique keys’ => array(
      ‘name’ => array(‘name’),
    ),
    ‘primary key’ => array(‘rid’),
    ‘indexes’ => array(
      ‘name_weight’ => array(‘name’, ‘weight’),
    ),
  );

  $schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique user ID.’,
        ‘default’ => 0,
      ),
      ‘name’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 60,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => ‘Unique user name.’,
      ),
      ‘pass’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 128,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => «User’s password (hashed).»,
      ),
      ‘mail’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 254,
        ‘not null’ => FALSE,
        ‘default’ => »,
        ‘description’ => «User’s e-mail address.»,
      ),
      ‘theme’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 255,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => «User’s default theme.»,
      ),
      ‘signature’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 255,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => «User’s signature.»,
      ),
      ‘signature_format’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 255,
        ‘not null’ => FALSE,
        ‘description’ => ‘The {filter_format}.format of the signature.’,
      ),
      ‘created’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘Timestamp for when user was created.’,
      ),
      ‘access’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘Timestamp for previous time user accessed the site.’,
      ),
      ‘login’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => «Timestamp for user’s last login.»,
      ),
      ‘status’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘size’ => ‘tiny’,
        ‘description’ => ‘Whether the user is active(1) or blocked(0).’,
      ),
      ‘timezone’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 32,
        ‘not null’ => FALSE,
        ‘description’ => «User’s time zone.»,
      ),
      ‘language’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 12,
        ‘not null’ => TRUE,
        ‘default’ => »,
        ‘description’ => «User’s default language.»,
      ),
      ‘picture’ => array(
        ‘type’ => ‘int’,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => «Foreign key: {file_managed}.fid of user’s picture.»,
      ),
      ‘init’ => array(
        ‘type’ => ‘varchar’,
        ‘length’ => 254,
        ‘not null’ => FALSE,
        ‘default’ => »,
        ‘description’ => ‘E-mail address used for initial account creation.’,
      ),
      ‘data’ => array(
        ‘type’ => ‘blob’,
        ‘not null’ => FALSE,
        ‘size’ => ‘big’,
        ‘serialize’ => TRUE,
        ‘description’ => ‘A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future version of Drupal.’,
      ),
    ),
    ‘indexes’ => array(
      ‘access’ => array(‘access’),
      ‘created’ => array(‘created’),
      ‘mail’ => array(‘mail’),
    ),
    ‘unique keys’ => array(
      ‘name’ => array(‘name’),
    ),
    ‘primary key’ => array(‘uid’),
    ‘foreign keys’ => array(
      ‘signature_format’ => array(
        ‘table’ => ‘filter_format’,
        ‘columns’ => array(‘signature_format’ => ‘format’),
      ),
    ),
  );

  $schema[‘users_roles’] = array(
    ‘description’ => ‘Maps users to roles.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘Primary Key: {users}.uid for user.’,
      ),
      ‘rid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘default’ => 0,
        ‘description’ => ‘Primary Key: {role}.rid for role.’,
      ),
    ),
    ‘primary key’ => array(‘uid’, ‘rid’),
    ‘indexes’ => array(
      ‘rid’ => array(‘rid’),
    ),
    ‘foreign keys’ => array(
      ‘user’ => array(
        ‘table’ => ‘users’,
        ‘columns’ => array(‘uid’ => ‘uid’),
      ),
      ‘role’ => array(
        ‘table’ => ‘roles’,
        ‘columns’ => array(‘rid’ => ‘rid’),
      ),
    ),
  );

  return $schema;
}

Como puede verse en el ejemplo, básicamente está utilizando una variable llamada «$schema» que al final de la función devuelve. Dicha variable es un array que contiene un índice por cada tabla que necesita generar.
Por ejemplo si queremos generar la tabla ‘users’, indicamos que sobre el array $schema metemos un nuevo elemento con el índice ‘users’ y como valor metemos otro array.
El primer elemento del array valor de la tabla ‘users’ será la descripción de la tabla, cuyo índice será ‘description’ y cuyo valor será una cadena de caracteres con la descripción de la tabla.
El segundo elemento tendrá como índice el nombre de ‘fields’ y contiene un array con las defniciones de los campos de la tabla.
Así tendremos un array $schema definido de esta manera:
$schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array()
);
En dicho array de campos (‘fields’), vamos introducciendo cada campo como un elemento cuyo índice es el nombre del campo y su valor es otro array con los metadatos del campo que queremos meter en la tabla, como el caso del campo ‘uid’…
$schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique user ID.’,
        ‘default’ => 0,
      )
     )
);
En este caso, el campo uid, tiene los siguientes elementos definidos:

  • type: tipo de campo definido por drupal
  • unasigned: valor booleano que permite definir si el campo es con o sin signo. Sólo disponible para campos numéricos.
  • not_null: valor booleano que nos indica si es campo puede ser null o no
  • description: descripción del campo
  • default: valor por defecto del campo

Como puede verse dicha definición de campo es una estructuración en forma de array de las típias configuraciones que solemos hacer en la propia base de datos cuando creamos un campo nuevo.
De esta manera ñadiríamos todos los campos que queremos que tenga la tabla, como distintos elementos del valor del array ‘fields’.
A continuación seguramente será necesario indicar de todos los campos cual (o cuales) es la clave primaria, en el caso de la tabla de users el campo ‘uid’ es el campo de clave primaria de la tabla, por lo que tenemos que insertar un nuevo elemento en el array principal $schema[‘users’] llamado ‘primary_key’ cuyo valor es un array con el nombre de los campos que son clave primaria. Por lo que el código quedaría así:
$schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique user ID.’,
        ‘default’ => 0,
      )
     ),
    ‘primary key’ => array(‘uid’)
);
 En el caso de la tabla users, tambiñen necesita hacer uso de índices sobre campos, para ello introduce también dentro del array $schema[‘users’] un elemento cuyo índice es ‘indexes’ cuyo valor debería ser un array con el nombre del índice y su valor un array con los nombres de los campos que queremos introducir en el índice. Así quedaría el array de la siguiente manera…
$schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique user ID.’,
        ‘default’ => 0,
      )//aquí introduciríamos el resto de elementos para definir el resto de campos de la tabla
     ),
    ‘primary key’ => array(‘uid’) ,
    ‘indexes’ => array(
      ‘access’ => array(‘access’),
      ‘created’ => array(‘created’),
      ‘mail’ => array(‘mail’),
    )
);
En este ejemplo, define 3 índices, sobre los campos access, created y mail. Por otra parte podemos definir índices únicos sobre campos, para ello debemos introducir un elemento más con índice ‘unique keys’ cuyo valor es un array con los nombres del índice y el valor de ese elemento es otro array con los campos que pertenecen a dicho array, en el ejemplo…
$schema[‘users’] = array(
    ‘description’ => ‘Stores user data.’,
    ‘fields’ => array(
      ‘uid’ => array(
        ‘type’ => ‘int’,
        ‘unsigned’ => TRUE,
        ‘not null’ => TRUE,
        ‘description’ => ‘Primary Key: Unique user ID.’,
        ‘default’ => 0,
      )//aquí introduciríamos el resto de elementos para definir el resto de campos de la tabla

     ),
    ‘primary key’ => array(‘uid’) ,
    ‘indexes’ => array(
      ‘access’ => array(‘access’),
      ‘created’ => array(‘created’),
      ‘mail’ => array(‘mail’),
    ),
    ‘unique keys’ => array(
      ‘name’ => array(‘name’),
    )
);
En el ejemplo crea un índice único llamado ‘name’  sobre el campo ‘name’. Dejamos para otro momento el índice ‘foreing keys’ por que tendríamos que explicar el modelo entero de users.

Debemos pensar que Drupal utilizará este hook para crear las tablas necesarias en la base de datos para el módulo, pero seguiríamos necesitando modificar el hook_install para introducir los datos iniciales en las tablas definidas en el hook_schema, como en el ejemplo…
// Insert a row for the anonymous user.
  db_insert(‘users’)
    ->fields(array(
      ‘uid’ => 0,
      ‘name’ => »,
      ‘mail’ => »,
    ))
    ->execute();
  Debido que al realizar la desinstalación del módulo user no hay que realizar más acciones que el borrado de las tablas generadas con la definición del hook_schema, el módulo user no necesita un hook_uninstall().

Práctica

  1. Genera un nuevo módulo en base a unos requisitos de base de datos dados.
  2. Define el hook_schema definiendo el modelo de base de datos
  3. Define el hook_install para introducir los datos iniciales en las tablas
  4. Prueba a realizar la instalación e activación del módulo, comprueba si las tablas se han generado correctamente.
  5. prueba a desactivar y desinstalar el módulo y mira a ver si ha borrado correctamente las tablas en la BBDD.

Referencias

Licencia Creative Commons

Comments

Leave a Reply

*

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Categorías de Cursos

RSS Cursos de Desarrollo

  • Introducción a las PWA (Progressive Web Apps) 21/02/2020
    Las PWA se han convertido es una alternativa a las aplicaciones web para colonizar de una manera más eficiente los móviles debido a que pueden funcionar de manera offline y optimizar el rendimiento de la aplicación desde el móvil. Si quieres enterarte de cómo crearlas, de los pros y contras no te pierdas el último […]
  • Introducción al Testing Web 10/02/2020
    Hemos publicado en nuestro canal de Youtube un vídeo grabado durante las clases de un curso de Python Avanzado. El tema es el de Testing Opensource hablado sobre la teoría de Testing, indicando los distintos tipos de pruebas e identificando las herramientas que se usan a la hora de probar una web.
  • Entrevista a Alejandro López CEO de Slimbook 10/02/2020
    Esta semana hemos entrevistado en República Web, a Alejandro López, CEO de Slimbook. Hablamos de sus productos y sobre equipos para desarrolladores, diseñadores web, fotógrafos, editores de vídeo y data scientist. Te lo vas a perder?
  • Gadgets para el formador itinerante: Router Wifi de Viaje 08/02/2020
    Muchas veces los formadores y profesionales itinerantes tenemos el problema de tener que conectarnos a Internet desde hoteles o cafeterías para seguir haciendo nuestro trabajo, en esta entrada veremos un router wifi de viaje muy interesante que he estado utilizando desde hace un tiempo y que me ha dado muy buenos resultados. Como todo en […]
  • Balanceadores de Carga 27/01/2020
    Dentro de la arquitectura web necesitamos cumplir con dos condiciones si queremos que nuestra arquitectura sea suficientemente sólida: Alta Disponibilidad y Alto Rendimiento, en esta entrada veremos cómo cumplir con estos dos principios. La alta disponibilidad trata de conseguir que un servicio tenga el máximo posible de tiempo de disponibilidad, es decir, que el servicio […]
  • Serie de Artículos de Docker 13/01/2020
    En esta entrada veremos cómo manejar Docker, en una serie de artículos explicativos. No te los pierdas He instalado Docker, ¿Y ahora qué? Docker Compose, para cuando quieres arrancar varios contenedores de manera coordinada
  • ¿Que Frameworks de Frontend son los más utilizados en el millón de páginas del Top de Alexa? 09/01/2020
    Partiendo de la idea del blog de de Andros, y del post sobre su estudio del uso de WordPress con un ejemplo de Clojure. He iniciado un proyecto secundario sobre el uso de las tecnologías usadas en las, más de 1.000.000 principales webs de Internet según Alexa. La idea, es la de ampliar la publicación […]
  • Artículos de administración de Servidores 08/01/2020
    Esta serie de artículos nos permiten saber cómo se instala y se configura un servidor desde cero: Nuevo Servidor NAS reciclado Acceso a servidor de la oficina desde fuera gracias a dinaip Configuración de un firewall de manera sencilla en Debian/Ubuntu
  • ¿Cuál es el uso de WordPress en los principales sitios de Internet según Alexa? 14/12/2019
    Empezamos con nuestra serie de publicaciones sobre tecnologías concretas que más se usan en Internet, en este caso con WordPress. ¿Quieres saber cómo es de importante y cuánto se utiliza? No te pierdas esta entrada.
  • Estudio de Uso de Tecnologías en el millón de páginas más vistas según Alexa 13/12/2019
    Partiendo de la idea del blog de de Andros, y del post sobre su estudio del uso de WordPress con un ejemplo de Clojure. He iniciado un proyecto secundario sobre el uso de las tecnologías usadas en las, más de 1.000.000 principales webs de Internet según Alexa. La idea, es la de ampliar la publicación […]

Si estás interesado en seguir formándote tenemos una serie de cursos gratuitos: http://cursosdedesarrollo.com/cursos/

También disponemos de algunos cursos de pago por si son de tu interés: https://cursosdedesarrollo.com/tienda/

Curso de Angular: https://cursosdedesarrollo.com/tienda/angular/

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