Làm thế nào để tôi thay đổi lớp loại thực thể?


9

Trong Drupal 8, bạn có thể tải một thực thể với:

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

Cái này tìm các định nghĩa thực thể và thấy rằng nút đó được xác định bởi Drupal \ node \ Entity \ Node - vì vậy (tôi đoán) Drupal \ node \ NodeStorage sẽ khởi tạo một thể hiện Drupal \ node \ Entity \ Node mới .

Những gì tôi muốn đạt được là phân lớp Drupal \ node \ Entity \ Node và có thể khởi tạo lớp con này khi thích hợp. Ví dụ: nếu tôi có một bài viết gói nút, sẽ có một lớp:

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

Và tôi sẽ gọi:

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

Và sự trở lại sẽ là Articlelớp con của tôi .

Tôi có thể đạt được điều này bằng cách tạo một loại thực thể mới và nối nó lại với các định nghĩa thực thể hiện có khác, ví dụ ví dụ về bài viết nút sẽ là lớp này:

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

Điều này hoạt động tốt (nhiều như tôi có thể thấy); Tuy nhiên, nó có mùi. Nó thêm một loại thực thể mới, không đúng sự thật và có thể gây ra những rắc rối khác trong tương lai.

Làm cách nào để xác định một lớp con cho gói thực thể để tải thực thể sẽ trả về một đối tượng của lớp đó?


1
Tôi không chắc bạn có thể cung cấp một lớp thực thể khác nhau cho mỗi gói; bạn có thể sử dụng hook_entity_type_alter()để thực hiện thay đổi rõ ràng hơn, nhưng tôi không biết làm thế nào bạn giới hạn điều đó với một gói cụ thể
Clive

Cảm ơn bạn Clive - có vẻ là một cái móc đầy hứa hẹn để điều tra!
itarato

Câu trả lời:


10

Tạo một lớp mới trong mô-đun của bạn mở rộng \Drupal\node\Entity\Node.

use Drupal\node\Entity\Node as BaseNode;

class MyNode extends BaseNode {
}

Thực hiện 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');
  }
}

Nhớ xây dựng lại bộ đệm.

Nó hoạt động tốt khi tải các nút thông qua dịch vụ quản lý loại thực thể và lưu trữ nút. Nó thậm chí hoạt động khi bạn chỉ sử dụng Drupal\node\Entity\Node::load($nid)nhờ vào load()chức năng này, nó chỉ là một trình bao bọc tĩnh cho cuộc gọi dịch vụ quản lý loại thực thể được cung cấp bởi Entitylớp được mở rộng từ Nodelớp.

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

Điều này cũng hoạt động tốt với entity_load_multiple()chức năng sắp bị loại bỏ , vì vậy tôi đoán điều này bao gồm tất cả các trường hợp sử dụng tiêu chuẩn để tải các nút.

Tất nhiên, nếu mô-đun của bạn làm điều này và mô-đun khác làm điều tương tự, bạn sẽ gặp vấn đề, nhưng tôi đoán đó không phải là tình huống phổ biến và nó chỉ có ý nghĩa đối với các trường hợp sử dụng rất cụ thể.


2
Xin lỗi nhưng không :) Câu hỏi là có một lớp khác nhau cho mỗi gói . Bạn đang thay đổi lớp cho tất cả các gói của nút loại thực thể. Điều đó không giống nhau.
Berdir

@Berdir, phải không bạn :( ... Có lớp học mỗi phương tiện bó rằng một lưu trữ thực thể cho nút sẽ phải được kéo dài quá để nó của phương pháp tải có thể ghi đè để sản xuất những mỗi lớp bó nào về cơ bản là một nhức đầu rất lớn..
SiliconMind

1
Vâng. drupal.org/node/2570593 là một trong những vấn đề mà tôi đã tham khảo nhưng quên thực sự liên kết đến trong câu trả lời của tôi.
Berdir

Tôi đã triển khai hook_entity_type_alter để đặt lớp tùy chỉnh. Nó hoạt động quá.
Yenya

Khi tôi thử phương pháp này, tôi nhận được một 'Drupal \ Element \ Plugin \ Exception \ PluginNotFoundException: Loại thực thể "nút" không tồn tại.' thông điệp. Tôi đang sử dụng hàm ablecore_entity_type_build trong tệp .module của mình. Và tôi có AbleNode.php trong thư mục / src / Entity / AbleNode /
Matt

2

Tôi gặp vấn đề tương tự và quyết định tạo ra một mô-đun thay đổi lớp loại thực thể của các thực thể Drupal thông qua hệ thống plugin. Hiện nay nó hỗ trợ thay đổi Node, UserFilecác lớp thực thể. Khi thay đổi Nodeentitiy, bạn có thể thay đổi lớp loại trên mỗi gói nút.

Kiểm tra mô tả mô-đun cho một ví dụ:

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

Mô-đun sử dụng hook_entity_type_alter () để đặt lớp trình xử lý trên các thực thể mà bạn cung cấp trong chú thích plugin của mình.



-1

Đây là một câu hỏi cũ, nhưng câu trả lời thực sự nên là:

Nếu bạn cần các hành vi khác nhau trên các gói, thì bạn nên sử dụng các loại thực thể khác nhau, không phải các gói khác nhau.

Các thực thể nội dung tùy chỉnh là công dân hạng 1 trong D8. Trên thực tế, chúng tôi ước tính mất khoảng 30 phút để đưa một thực thể nội dung tùy chỉnh mới đến cấp độ của nút đó (điều này thực sự bắt nguồn từ việc thêm Giao diện người dùng để có bảng điều khiển bên đẹp và các trường bí danh / sửa đổi.) không bao gồm thêm các trang dịch, nhưng đó không phải là nhiều hơn nữa.

Nếu bạn chưa thấy nó, hãy xem các tính năng tạo: tùy chỉnh: thực thể của Drupal Console.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.