Bagaimana cara mengubah kelas tipe entitas?


9

Di Drupal 8 Anda dapat memuat entitas dengan:

$node = \Drupal::entityManager()->getStorage('node')->load(123);

Ini mencari definisi entitas dan menemukan bahwa node didefinisikan oleh Drupal \ node \ Entity \ Node - jadi (saya kira) Drupal \ node \ NodeStorage akan instantiate contoh Drupal \ node \ Entity \ Node yang baru .

Apa yang ingin saya capai adalah subkelas Drupal \ node \ Entity \ Node dan dapat membuat instance subkelas ini ketika itu sesuai. Sebagai contoh jika saya memiliki artikel kumpulan simpul, akan ada kelas:

namespace Drupal\my_module\Entity\Article;
class Article extends Drupal\node\Entity\Node {
}

Dan saya akan menelepon:

$node = \Drupal::entityManager()->getStorage('node_article')->load(123);

Dan kembalinya akan menjadi Articlesubclass saya .

Saya bisa mencapai ini dengan membuat tipe entitas baru dan menghubungkannya kembali ke definisi entitas lain yang sudah ada, misalnya contoh node-article adalah kelas ini:

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);

Ini berfungsi dengan baik (sebanyak yang saya bisa lihat); Namun, baunya. Itu menambahkan tipe entitas baru, yang tidak benar, dan mungkin menyebabkan masalah lain di masa depan.

Bagaimana cara mendefinisikan subclass untuk bundel entitas sehingga memuat entitas akan mengembalikan objek kelas itu?


1
Saya tidak yakin Anda bisa memberikan kelas entitas yang berbeda per bundel; Anda dapat menggunakan hook_entity_type_alter()untuk membuat perubahan lebih bersih, tapi saya tidak tahu bagaimana Anda akan membatasi itu pada bundel tertentu
Clive

Terima kasih Clive - yang kelihatannya kait yang menjanjikan untuk diselidiki!
itarato

Jawaban:


10

Buat kelas baru di modul Anda yang memanjang \Drupal\node\Entity\Node.

use Drupal\node\Entity\Node as BaseNode;

class MyNode extends BaseNode {
}

Implementasikan hook_entity_type_build().

use Drupal\Core\Entity\EntityTypeInterface;

/**
 * @param EntityTypeInterface[] $entity_types
 */
function my_module_entity_type_build(&$entity_types) {
  if (isset($entity_types['node'])) {
    $entity_types['node']->setClass('Drupal\my_module\Entity\MyNode');
  }
}

Ingatlah untuk membangun kembali cache.

Ini berfungsi dengan baik ketika memuat node melalui layanan jenis entitas manajer dan penyimpanan node. Ia bahkan bekerja ketika Anda hanya menggunakan Drupal\node\Entity\Node::load($nid)berkat fakta bahwa load()fungsi ini hanya pembungkus statis untuk panggilan layanan manajer tipe entitas yang disediakan oleh Entitykelas yang diperluas dari Nodekelas.

// Part of Entity class for reference
abstract class Entity implements EntityInterface {
  /**
   * Loads an entity.
   *
   * @param mixed $id
   *   The id of the entity to load.
   *
   * @return static
   *   The entity object or NULL if there is no entity with the given ID.
   */
  public static function load($id) {
    $entity_manager = \Drupal::entityManager();
    return $entity_manager->getStorage($entity_manager->getEntityTypeFromClass(get_called_class()))->load($id);
  }
}

Ini juga berfungsi baik dengan fungsi yang akan segera dihapus entity_load_multiple(), jadi saya kira ini mencakup semua kasus penggunaan standar untuk memuat node.

Tentu saja, jika modul Anda melakukan ini dan modul lain melakukan hal yang sama, Anda akan memiliki masalah, tapi saya kira itu bukan skenario umum, dan itu masuk akal hanya untuk kasus penggunaan yang sangat spesifik.


2
Maaf tapi tidak :) Pertanyaannya adalah memiliki kelas yang berbeda per bundel . Anda mengubah kelas untuk semua kumpulan simpul tipe entitas. Itu tidak sama.
Berdir

@Berdir, kanan Anda :( ... Memiliki kelas per bundel berarti bahwa penyimpanan entitas untuk simpul juga harus diperpanjang sehingga metode pemuatannya dapat diganti untuk menghasilkan kelas per bundel. Yang pada dasarnya adalah satu sakit kepala besar.
SiliconMind

1
Ya. drupal.org/node/2570593 adalah salah satu masalah yang saya rujuk tetapi lupa untuk benar-benar terhubung ke dalam jawaban saya.
Berdir

Saya telah mengimplementasikan hook_entity_type_alter untuk mengatur kelas khusus. Ini juga berhasil.
Yenya

Ketika saya mencoba metode ini saya mendapatkan 'Drupal \ Component \ Plugin \ Exception \ PluginNotFoundException: Tipe entitas "node" tidak ada.' pesan. Saya menggunakan fungsi ablecore_entity_type_build dalam file .module saya. Dan saya memiliki AbleNode.php saya di / src / Entity / AbleNode / folder
Matt

2

Saya mengalami masalah yang sama dan memutuskan untuk membuat modul yang mengubah kelas tipe entitas entitas Drupal melalui sistem plugin. Saat ini mendukung mengubah Node, Userdan Filekelas entitas. Saat mengubah Nodeentitiy Anda dapat mengubah tipe kelas per bundel node.

Lihat deskripsi modul untuk contoh:

https://www.drupal.org/project/entity_type_class

Modul ini menggunakan hook_entity_type_alter () untuk mengatur kelas penangan pada entitas yang Anda berikan dalam anotasi plugin Anda.



-1

Ini adalah pertanyaan lama, tetapi jawaban sebenarnya adalah:

Jika Anda memerlukan perilaku berbeda di bundel, maka Anda harus menggunakan tipe entitas yang berbeda, bukan bundel berbeda.

Entitas Konten Khusus adalah warga negara kelas 1 di D8. Bahkan kami memperkirakan bahwa dibutuhkan sekitar 30 menit untuk mendapatkan entitas konten kustom baru ke tingkat simpul itu (yang benar-benar hanya turun untuk menambahkan Formulir UI untuk mendapatkan panel samping yang bagus, dan bidang alias / revisi.) Ini tidak termasuk menambahkan halaman terjemahan, tapi itu tidak lebih.

Jika Anda belum melihatnya, lihat fitur Drupal Console's: custom: entity.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.