Aanmaken van custom content
Doelgroep
Deze documentatie is in de eerste plaats bedoeld voor ontwikkelaars met ervaring in objectgeoriënteerd PHP-programmeren, Drupal 6 of Drupal 7, en ook voor degenen die de principes van Drupal 8 willen leren.
Documentatie over het aanmaken van een content entity type in Drupal 8 bevat een volledige lijst met beschikbare opties.
Een inhoudstype zonder bundle opbouwen in Drupal 8
In dit geval maken we een Drupal 8-contentobject aan dat geen enkele bundle heeft.
De entiteit implementeert de Field API niet, dus blijft deze in de code. Toch kan dit een nuttig skelet zijn om Content Entities op te bouwen, aangezien we later complexere gegevens importeren.
Ten slotte, waar OOP-concepten voorkomen, zal ik verwijzen naar de relevante documentatie.
Achtergrond
Onze module heet advertiser.
Ons content entity type heet advertiser.
Onze nieuwe Drupal 8-contententity advertiser zal de volgende velden hebben:
- UUID
- ID
Definitie van het contentobject in Drupal 8
Allereerst: alle custom objecten staan nu in modules/custom in plaats van in sites/all/modules/custom.
Binnen ons custom object ziet de uiteindelijke bestandsstructuur er als volgt uit:
modules/custom/advertiser$
├── advertiser.info.yml
└── src
└── Entity
└── Advertiser.php
Ter referentie kun je de kant-en-klare Advertiser entity bekijken samen met extra toevoegingen zoals tests en constraint-plugins, maar voorlopig houden we het eenvoudig.
Info-bestand
We beginnen met het definiëren van onze custom module in module_name.info.yml. Dit spreekt voor zich:
name: Advertiser type: module description: 'Barebones advertiser entity' package: custom core: 8.x
Entity-skelet
Ondertussen zijn de basisklasse van de Advertiser-entity en het bijbehorende schema gedefinieerd in src/Entity/Advertiser.php.
Het eerste dat we doen, is de namespace voor onze Advertiser Entity Class definiëren. Dit is handig wanneer we onze klassen willen gebruiken.
namespace Drupal\advertiser\Entity;
Nu is het tijd om onze entiteit te definiëren, wat we doen met annotatie.
Dit is de feitelijke definitie van het objecttype dat wordt ingelezen en gecachet, dus zorg ervoor dat je de cache wist na elke wijziging.
<?php
/**
* Definieert de advertiser entity.
*
* @ingroup advertiser
*
* @ContentEntityType(
* id = "advertiser",
* label = @Translation("Advertiser"),
* base_table = "advertiser",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* },
* )
*/
?>
Aangezien dit een lege entiteit is, gebruiken we slechts enkele properties en geen handlers zoals de Access-module.
We hebben een functionele module die onze custom contententity definieert, maar we zullen merken dat de tabel “advertiser” niet in de database is aangemaakt.
$ drush sql-cli mysql> SHOW TABLES;
Dat komt doordat onze klasse geen methodes bevat die expliciet met de database interageren. Bovendien hebben we een beschrijving nodig van het absolute minimum aan methodes die noodzakelijk zijn voor een correcte interactie van de entiteit met de database.
ContentEntityBase
Gewoonlijk kunnen we klassen toevoegen door bovenaan ons script na de namespace-definitie use Drupal\Core\Entity\ContentEntityBase; toe te voegen. Dit maakt deze methodes beschikbaar voor onze eigen klasse, die ze kan uitbreiden of, in het geval van interfaces, implementeren.
We doen twee dingen: we breiden de bestaande klasse ContentEntityBase uit, die al de benodigde methodes voor database-interactie bevat, en we implementeren ContentEntityInterface om de methodes te beschrijven...
... die we nodig hebben voor toegang tot onze database. Dit beschrijft NIET hoe we dat doen. Dat doet de klasse die de interface implementeert. We kunnen deze interface zo vaak implementeren als we willen, op zoveel manieren als we nodig hebben. Daarna kunnen we wisselen tussen interface-implementaties zonder ons bestaande code te breken, omdat de interface definieert hoe we ermee werken, ongeacht hoe het intern werkt. - https://secure.php.net/manual/en/language.oop5.interfaces.php
Dit alles betekent dat we het volgende krijgen: vergeet niet alle nieuwe klassen toe te voegen met een use-statement bovenaan ons script:
class Advertiser extends ContentEntityBase implements ContentEntityInterface {
Maar we moeten deze nieuwe nuttige methodes nog gebruiken om iets in de database te plaatsen. We beginnen met de basisvelden van onze entiteit.
baseFieldDefinitions
De methode baseFieldDefinitions komt uit de klasse ContentEntityBase, die we uitbreiden.
Er is één parameter vereist:
De definitie van het objecttype. Nuttig wanneer één klasse wordt gebruikt voor meerdere, eventueel dynamische objecttypen.
En dit geeft terug:
Een array van basisvelddocumentaties voor het objecttype, gebaseerd op veldnamen.
We implementeren dit dus als volgt:
<?php
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
// Standaardveld, gebruikt als unieke primaire index.
$fields['id'] = BaseFieldDefinition::create('integer')
->setLabel(t('ID'))
->setDescription(t('The ID of the Advertiser entity.'))
->setReadOnly(TRUE);
// Standaardveld, uniek buiten de scope van het huidige project.
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The UUID of the Advertiser entity.'))
->setReadOnly(TRUE);
return $fields;
}
?>
Het is de moeite waard om op te merken:
“Biedt definities van basisvelden voor een objecttype.”
- Dit is een public static methode uit FieldableEntityInterface.
“Klasse voor het definiëren van entity-velden.”
- Alle methodes die we nodig hebben voor het aanmaken van velden, toevoegen van constraints, enz.
Volledige entiteit
Dus, alles bij elkaar ziet het er zo uit:
<?php
namespace Drupal\advertiser\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityInterface;
/**
* Defines the advertiser entity.
*
* @ingroup advertiser
*
* @ContentEntityType(
* id = "advertiser",
* label = @Translation("advertiser"),
* base_table = "advertiser",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* },
* )
*/
class Advertiser extends ContentEntityBase implements ContentEntityInterface {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
// Standaardveld, gebruikt als unieke primaire index.
$fields['id'] = BaseFieldDefinition::create('integer')
->setLabel(t('ID'))
->setDescription(t('The ID of the Advertiser entity.'))
->setReadOnly(TRUE);
// Standaardveld, uniek buiten de scope van het huidige project.
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The UUID of the Advertiser entity.'))
->setReadOnly(TRUE);
return $fields;
}
}
?>
Na installatie van je module zou je moeten zien dat de tabel “advertiser” aan de database is toegevoegd!
$ drush sql-cli mysql> SHOW TABLES;
of
drush sqlq "show tables like 'advertiser'" drush sqlq "describe advertiser"
Als je module al geïnstalleerd is, moet je een entity update uitvoeren.
In #2976035: CRUD-operaties met objecttype moeten het laatst geïnstalleerde objecttype en veldopslagdefinities gebruiken, is de mogelijkheid om dit remote op verzoek te doen verwijderd, zie meer informatie in de bijbehorende change record.
Zie ook de module Devel Entity Updates.