Introduction to Entity API in Drupal 8

The Drupal 8 entity system

Entities are typed classes with methods

Generic methods

$entity->id()

Entity type specific methods

$node->getTitle()

Both types are defined and documented in interfaces.

Background

The Entity System was introduced late in the Drupal 7 development cycle with basic standards for how entities were loaded. The contributed entity.module expanded the API further by adding support for saving and deleting entities and many other improvements.

The majority of those improvements are now included in Drupal 8. Entity validation is now in its own API (which could validate an Entity saved via REST, rather than a form, for example).

Two variants

Entity types in core come in two variants.

Configuration Entity

Used by the Configuration System. Supports translations and can provide custom defaults for installations. Configuration entities are stored within the common config database table as rows.

Content Entity

Consist of configurable and base fields, and can have revisions and support translations. Content entities are stored within a custom database table as rows. The table name is the same as the content entity "id", and the columns are defined by the entity's "baseFieldDefinitions" method.

Bundles

Bundles are different variants of an entity type. For example, with the node entity type, the bundles are the different node types, such as 'article' and 'page'.

Typically, a bundle is represented by a Configuration Entities, though other models exist in contrib modules. So in the node example, the 'article' node type is itself a configuration entity. The  configuration stores the differences between the content entity types, such as settings and fields. When creating a new entity type that has bundle entities, you will create both a Content Entity that will manage the content's details and operations, and a Configuration Entity that will handle the differences between the content entity types.

Annotations

When creating a new entity type, you'll need to use the annotations system built into core. Annotations look like docblock comments above the class, but are parsed and cached by Drupal core. In a lot of ways annotations replace some of the older style hooks used in Drupal 7.

Annotation parser

Annotations are read and parsed at runtime by an annotation engine. Drupal 8 uses the Doctrine annotation parser, which turns it into an object that PHP can use.

Syntax - The annotation syntax is surrounded with @ClassName(), is predominantly made up of key/value pairs, and can contain arrays that use curly braces. Top level keys must not be surrounded with quotation marks, while array keys must. Each key/value pair should be on their own line, and that line should end with a comma. Certain functions can be executed on values, notably the @Translation()function.

Non-working example of annotation syntax:

/**

 * @ContentEntityType(

 *   id = "my_entity_type_id",

 *   label = @Translation("My entity type label"),

 *   example_pair = "this_examples_value",

 *   example_array = {

 *     "array_key" = "array_value",

 *     "some_other_key" = "some_other_value",

 *   },

 * )

 */

Common top level annotations

Key = "Example Value",

Description

Entity Variant

id = "node",

The machine-name for the entity type.

Content & Config

label = @Translation("Node"),

The human readable name for the entity type.

Content & Config

admin_permission = "administer nodes",

A permission that allows administrative access to configure and manage the entity type. This is necessary if your entity does not define an "access" handler.

Content & Config

bundle_label = @Translation("Content type"),

The optional human readable name for bundle entity type.

Content

bundle_entity_type = "node_type",

When creating a Content Entity that has bundles, this value should be the "id" of the Configuration Entity. In this case, "node_type" is a Configuration Entity.

Content

base_table = "node",

Database table name for the entity type.

Content

fieldable = TRUE,

(boolean) Whether or not this entity type can be extended through the Field UI.

Content

field_ui_base_route = "entity.node_type.edit_form",

The name of the route the Field UI is attached to on a fieldable entity.

Content

Handlers

Handlers are defined in the entity annotation as an array. They support the entity by mapping certain parts of its execution to other PHP classes. Those classes will "handle" the assigned parts of the entity's execution.

Storage handler - Supports loading, saving and deleting entities in storage (database). This includes default support for revisions, translations and configurable fields.
Example: "storage" = "Drupal\node\NodeStorage",

Form handlers - In any entity's handlers annotation there are multiple form handlers that map the entity's add, edit, and delete forms to other PHP classes. 
Example: 

"form" = {

  "add" = "Drupal\block\BlockForm",

  "edit" = "Drupal\block\BlockForm",

  "delete" = "Drupal\block\Form\BlockDeleteForm",

}

Alternatively, you can define a "default" form to handle both the "add" and "edit" form instead of defining them separately. Worth noting is that the "delete" form will almost always be handled by a separate class from the other forms. This is because the delete form is generally a "confirmation form" that simply asks if the user is sure they want to delete the entity.

View builder - This handler provides a class that will handle the output of the entity when viewed by the end user. For example, when visiting a node on a Drupal 8 site, entity's output is handled by the NodeViewBuilder class.
Example: "view_builder" = "Drupal\node\NodeViewBuilder",

List builder - The list builder class will handle the list of entities for administrative purposes. This class will define the contents of the headers, rows, and operations when visiting the entities management page for the entity. For example, when visiting the /admin/content URI of your Drupal site, the table contents are provided by the Node entity's list builder class.
Example: "list_builder" = "Drupal\node\NodeListBuilder",

Route provider - An optional handler that, if implemented, generates routes for your entity management. Implementing this handler can replace the need for entity routes defined in the routing.yml file of your module. Note, the route_provider works in conjunction with the Links defined on your entity (see example below Links section). The route_provider annotation is an array.
Example: 

"route_provider" = {

  "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",

}

Access - The access handler can be used to dynamically check permissions for your entity. It is a mapping to a class that implements the EntityAccessControlHandlerInterface. Core provides an implementation of this interface as EntityAccessControlHandler, but for reliable control over your entity you will want to extend that class with your own.
Example: "access" = "NodeAccessControlHandler",

Views data - The views_data handler allows an entity to extend the Views module with custom data provided by your entity. This can be for adding your entity's baseFieldDefinitions as Views fields, joining tables on entity relationships, or other Views related data alterations.
​​​​​​​Example: "views_data" = "Drupal\node\NodeViewsData", 

Storage - You can define a storage handler to extend the default storage methods of your entity. By default, Content Entities use Drupal\Core\Entity\Sql\SqlContentEntityStorage while Config Entities use Drupal\Core\Config\Entity\ConfigEntityStorage. You may want to do this to provide additional methods for gathering entity revision ids, or determining the number of translations an entity has.
Example: "storage" = "Drupal\node\NodeStorage", 

Storage schema - The storage_schema handler can be implemented to further alter the entity's database storage settings. For instance, adding additional table indexes or foreign keys.
Example: "storage_schema" = "Drupal\node\NodeStorageSchema", 

Translation - The translation handler can be used to alter the way in which your entity forms interact with translations.
Example: "translation" = "Drupal\node\NodeTranslationHandler", 

Full handlers example:

Drupal core provides handlers that you can use out of the box, but in many cases you'll want to extend these classes with your own for greater control and customization of your entity. This example shows a more-complete handlers annotation, using the core classes you can extend.

handlers = {

  "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",

  "list_builder" = "Drupal\Core\Entity\EntityListBuilder",

  "access" = "Drupal\Core\Entity\EntityAccessControlHandler",

  "views_data" = "Drupal\views\EntityViewsData",

  "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",

  "storage_schema" = "Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema",

  "translation" = "Drupal\content_translation\ContentTranslationHandler",

  "form" = {

    "default" = "Drupal\Core\Entity\ContentEntityForm",

    "add" = "Drupal\Core\Entity\ContentEntityForm",

    "edit" = "Drupal\Core\Entity\ContentEntityForm",

    "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",

  },

  "route_provider" = {

    "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",

  },

},

Links

Links are defined in the entity annotation with the array syntax. Links have a specific set of keys whose value are URIs where the entity type or single entities of that type can be managed. Both Content and Configuration Entities can have these links defined.

Example:

id = "node",

handlers = {

  "route_provider" = {

    "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider"

  }

},

links = {

  "canonical" = "/node/{node}",

  "add-page" = "/node/add",

  "add-form" = "/node/add/{node_type}",

  "edit-form" = "/node/{node}/edit",

  "delete-form" = "/node/{node}/delete",

  "collection" = "/admin/content",

},

Note, this is not taken verbatim from the Node module, it is only an example.

Creating these links does not automatically create the routes for those URIs. To make these links accessible, your module will need to implement its own routing.yml file, or use a "route_provider" handler in the entity annotation.

Links & Route Provider

The above links working together with a route_provider will make the following named routes available to Drupal.
 

Links Key

Route Name

Route Example URI

Description

canonical

entity.node.canonical

/node/1

View a specific node

add-page

entity.node.add_page

/node/add

Select bundle of node to be added

add-form

entity.node.add_form

/node/add/article

Add a node (of a specific bundle)

edit-form

entity.node.edit_form

/node/1/edit

Edit form for a specific node

delete-form

entity.node.delete_form

/node/1/delete

Delete form for a specific node

collection

entity.node.collection

/admin/content

View all nodes as a list

Using Links

These links can be accessed with an entity's toUrl() method:

$view_url_object = $entity->toUrl();  // Default is 'canonical'

$edit_url_string = $entity->toUrl('edit-form')->toString();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值