A partir de la versión 9.3, se han incluido las llamadas "bundle classes". Esto permite que, por ejemplo, se pueda usar una clase específica para los nodos de un determinado tipo (por ejemplo, usar una clase Article extendiendo de Node en lugar de la clase base directamente).
Estas clases pueden ser generadas con drush a partir de la versión 11. Ej (para un hipotético módulo vacío "web"):
user@web:/var/www/html$ drush gen entity:bundle-class
Welcome to entity-bundle-class generator!
–––––––––––––––––––––––––––––––––––––––––––
Module machine name [web]:
➤
Entity type:
[ 1] Bloque personalizado
[ 2] Recortar
[ 3] Archivo
[ 4] Multimedia
[ 5] Enlace de menú personalizado
[ 6] Contenido
[ 7] Alias de URL
[ 8] Redirección
[ 9] Término de la taxonomía
[10] Usuario
[11] Párrafo
➤ 6
Bundles, comma separated:
[1] Evento
➤ 1
Class for Evento bundle [EventBundle]:
➤
Use a base class? [No]:
➤ Yes
Base class [NodeBundle]:
➤
The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• /var/www/html/web/modules/custom/web/web.module
• /var/www/html/web/modules/custom/web/src/Entity/Bundle/NodeBundle.php
• /var/www/html/web/modules/custom/web/src/Entity/Bundle/EventBundle.php
Eso genera los siguientes archivos:
/var/www/html/web/modules/custom/web/web.module
<?php /** * @file * Primary module hooks for Web module. */ /** * Implements hook_entity_bundle_info_alter(). */ function web_entity_bundle_info_alter(array &$bundles): void { if (isset($bundles['node']['event'])) { $bundles['node']['event']['class'] = \Drupal\web\Entity\Bundle\EventBundle::class; } }
/var/www/html/web/modules/custom/web/src/Entity/Bundle/NodeBundle.php
<?php namespace Drupal\web\Entity\Bundle; use Drupal\node\Entity\Node; /** * A base bundle class for node entities. */ abstract class NodeBundle extends Node { }
/var/www/html/web/modules/custom/web/src/Entity/Bundle/EventBundle.php
<?php namespace Drupal\web\Entity\Bundle; /** * A bundle class for node entities. */ class EventBundle extends NodeBundle { }
A partir de ahora, cada vez que se cargue un nodo de tipo evento (event), lo hará automáticamente con la clase "EventBundle" en lugar de la típica "Node". Ya solo con esto se puede empezar a crear código específico para dicho tipo de contenido.
Por poner un ejemplo, si el tipo de contenido Evento tiene un campo de rango de fecha (fecha inicio y fin en el mismo campo), pueden obtenerse de manera sencilla sus fechas por separado para su uso en plantillas (por defecto se permiten los métodos get*()).
/var/www/html/web/modules/custom/web/src/Entity/Bundle/EventBundle.php
<?php namespace Drupal\web\Entity\Bundle; /** * A bundle class for node entities. */ class EventBundle extends NodeBundle { /** * {@inheritdoc} */ public function getStartDate(): string { return $this->field_event_date->start_date->format('Y-m-d'); } /** * {@inheritdoc} */ public function getEndDate(): string { return $this->field_event_date->end_date->format('Y-m-d'); } }
/var/www/html/web/themes/custom/web_theme/templates/content/node--event--full.html.twig
<article{{ attributes }}>
{{ title_prefix }}
<h2>{{ label }}</h2>
{{ title_suffix }}
{{ node.getStartDate() }}
{{ node.getEndDate() }}
</article>
Si se tienen varios tipos de contenido y se quiere usar una clase para algunos específicos y otra base (pero que no sea Node directamente), en el hook_entity_bundle_info_alter() puede añadirse lo siguiente:
foreach ($bundles['node'] as $bundle => $definition) { $bundles['node'][$bundle]['class'] = match ($bundle) { 'blog_post' => BlogPost::class, 'event' => Event::class, 'service' => Service::class, default => NodeBundle::class, }; }
Nota: En este caso habría que eliminar el "abstract" de la clase "NodeBundle".
Por último, es recomendable usar interfaces, por ejemplo para typehinting de funciones:
/var/www/html/web/modules/custom/web/src/Entity/Bundle/EventBundle.php
class EventBundle extends NodeBundle implements EventBundleInterface { ... }
/var/www/html/web/modules/custom/web/src/Entity/Bundle/EventBundleInterface.php
interface EventBundleInterface extends NodeInterface { ... }
Comentarios
Añadir nuevo comentario