In Drupal 8 können Sie eine Entität laden mit:
$node = \Drupal::entityManager()->getStorage('node')->load(123);
Dies sucht nach den Entitätsdefinitionen und stellt fest, dass der Knoten durch Drupal \ node \ Entity \ Node definiert ist. Drupal \ node \ NodeStorage instanziiert also (glaube ich) eine neue Drupal \ node \ Entity \ Node- Instanz.
Was ich erreichen möchte, ist die Unterklasse Drupal \ node \ Entity \ Node und die Möglichkeit, diese Unterklasse zu instanziieren, wenn es angebracht ist. Wenn ich beispielsweise einen Artikel zum Knotenpaket habe, gibt es eine Klasse:
namespace Drupal\my_module\Entity\Article;
class Article extends Drupal\node\Entity\Node {
}
Und ich würde anrufen:
$node = \Drupal::entityManager()->getStorage('node_article')->load(123);
Und die Rückkehr wäre meine Article
Unterklasse.
Ich kann dies erreichen, indem ich einen neuen Entitätstyp erstelle und ihn mit anderen vorhandenen Entitätsdefinitionen verdrahtete. Das Beispiel für einen Knotenartikel wäre beispielsweise diese Klasse:
namespace Drupal\my_module\Entity;
use Drupal\node\Entity\Node;
/**
* @ContentEntityType(
* id = "node_article",
* label = @Translation("Content"),
* bundle_label = @Translation("Content type"),
* handlers = {
* "storage" = "Drupal\node\NodeStorage",
* "storage_schema" = "Drupal\node\NodeStorageSchema",
* "view_builder" = "Drupal\node\NodeViewBuilder",
* "access" = "Drupal\node\NodeAccessControlHandler",
* "views_data" = "Drupal\node\NodeViewsData",
* "form" = {
* "default" = "Drupal\node\NodeForm",
* "delete" = "Drupal\node\Form\NodeDeleteForm",
* "edit" = "Drupal\node\NodeForm"
* },
* "route_provider" = {
* "html" = "Drupal\node\Entity\NodeRouteProvider",
* },
* "list_builder" = "Drupal\node\NodeListBuilder",
* "translation" = "Drupal\node\NodeTranslationHandler"
* },
* base_table = "node",
* data_table = "node_field_data",
* revision_table = "node_revision",
* revision_data_table = "node_field_revision",
* translatable = TRUE,
* list_cache_contexts = { "user.node_grants:view" },
* entity_keys = {
* "id" = "nid",
* "revision" = "vid",
* "bundle" = "type",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid",
* "status" = "status",
* "uid" = "uid",
* },
* bundle_entity_type = "node_type",
* field_ui_base_route = "entity.node_type.edit_form",
* common_reference_target = TRUE,
* permission_granularity = "bundle",
* links = {
* "canonical" = "/node/{node}",
* "delete-form" = "/node/{node}/delete",
* "edit-form" = "/node/{node}/edit",
* "version-history" = "/node/{node}/revisions",
* "revision" = "/node/{node}/revisions/{node_revision}/view",
* }
* )
*/
class Article extends Node { }
// Results my Article sub type.
$node = \Drupal::entityManager()->getStorage('node_article')->load(123);
Das funktioniert gut (so viel ich sehen kann); es riecht jedoch. Es wird ein neuer Entitätstyp hinzugefügt, der nicht wahr ist und in Zukunft andere Probleme verursachen kann.
Wie definiere ich eine Unterklasse für ein Entitätspaket, damit beim Laden der Entität ein Objekt dieser Klasse zurückgegeben wird?
hook_entity_type_alter()
, um die Änderung sauberer zu machen, aber ich weiß nicht, wie Sie das auf ein bestimmtes Bundle beschränken würdenAntworten:
Erstellen Sie eine neue Klasse in Ihrem Modul, die erweitert wird
\Drupal\node\Entity\Node
.Implementieren
hook_entity_type_build()
.Denken Sie daran, den Cache neu zu erstellen.
Es funktioniert einwandfrei, wenn Knoten über den Entity Type Manager-Dienst und den Knotenspeicher geladen werden. Es funktioniert sogar, wenn Sie es nur verwenden
Drupal\node\Entity\Node::load($nid)
, da dieseload()
Funktion nur ein statischer Wrapper für den Serviceaufruf des Entity Type Managers ist, der von derEntity
Klasse bereitgestellt wird, die von der Klasse erweitert wirdNode
.Dies funktioniert auch gut mit der
entity_load_multiple()
Funktion, die bald entfernt werden soll. Ich denke, dies deckt alle Standardanwendungsfälle zum Laden von Knoten ab.Wenn Ihr Modul dies tut und ein anderes Modul dasselbe tut, haben Sie natürlich ein Problem, aber ich denke, es ist kein allgemeines Szenario, und es ist nur für ganz bestimmte Anwendungsfälle sinnvoll.
quelle
Ich hatte das gleiche Problem und entschied mich, ein Modul zu erstellen, das die Entitätstypklasse von Drupal-Entitäten über das Plugin-System ändert. Derzeit unterstützt verändern sie das
Node
,User
undFile
Entitätsklassen. Wenn Sie dieNode
Berechtigung ändern, können Sie die Typklasse pro Knotenpaket ändern.In der Modulbeschreibung finden Sie ein Beispiel:
https://www.drupal.org/project/entity_type_class
Das Modul verwendet hook_entity_type_alter () , um eine Handlerklasse für Entitäten festzulegen , die Sie in Ihrer Plugin-Annotation angeben .
quelle
Dieses Modul bietet Ihnen auch echte Bundle-Klassen - https://github.com/amcgowanca/discoverable_entity_bundle_classes
quelle
Dies ist eine alte Frage, aber die wirkliche Antwort sollte sein:
Wenn Sie ein unterschiedliches Verhalten zwischen Bundles benötigen, sollten Sie unterschiedliche Entitätstypen verwenden, nicht unterschiedliche Bundles.
Benutzerdefinierte Inhaltseinheiten sind Bürger erster Klasse in D8. Wir schätzen, dass es ungefähr 30 Minuten dauert, bis eine neue benutzerdefinierte Inhaltsentität auf die Ebene des Knotens gebracht wird (was wirklich nur darauf hinausläuft, die Formular-Benutzeroberfläche hinzuzufügen, um das schöne Seitenfenster und die Alias- / Revisionsfelder zu erhalten) beinhaltet nicht das Hinzufügen der Übersetzungsseiten, aber das ist nicht viel mehr.
Wenn Sie es nicht gesehen haben, sehen Sie sich die Funktionen generate: custom: entity der Drupal Console an.
quelle