2. hello!
I am Igor Karpilenko
Drupal developer from Deweb studio
https://www.drupal.org/u/hamrant
https://www.facebook.com/hamrant
https://www.linkedin.com/in/hamrant
4. The problem
PHP is a very loosely typed language. It doesn’t have a clear definition of
the different types of data it deals with.
Therefore Drupal used to be the same. For example, there was no
consistent way of telling if a field value is a string, an integer or a
timestamp.
5. Typed Data
The Typed Data API was created to provide developers with a
consistent way of interacting with data in different ways.
Not only does the API allow you to interact with the actual data, it also
provides means of fetching more information, or metadata, about the
actual data.
6. The Typed Data API is a low level, generic and reusable object oriented
API that appears at multiple levels of the Drupal 8 architecture.
Take for example, the EntityAdapter, which extends TypedData and
acts as a wrapper for an Entity. Or FieldItemBase, which is an
unwrapped extension of TypedData.
7. Each data type in the Typed Data API is a plugin class (annotation class
example: DrupalCoreTypedDataAnnotationDataType).
These plugins are managed by the typed_data_manager service (by
default DrupalCoreTypedDataTypedDataManager).
Each data object encapsulates a single piece of data, provides access
to the metadata, and provides validation capability.
9. The Typed Data API interfaces
List
Data
Primitive
Data
Complex
Data
10. Primitive Data
Implementations of this interface are used for something that
represents a single piece of typed data, like a string or integer.
This is the smallest building block in the Typed Data API.
12. PrimitiveInterface methods
getValue() - Gets the primitive data value
setValue($value) - Sets the primitive data value
getCastedValue() - Gets the primitive data value casted to the
correct PHP type
13. Primitive data type example
/**
* The integer data type.
*
* The plain value of an integer is a regular PHP integer. For setting the value
* any PHP variable that casts to an integer may be passed.
*
* @DataType(
* id = "integer",
* label = @Translation("Integer")
* )
*/
class IntegerData extends PrimitiveBase implements IntegerInterface
/**
* {@inheritdoc}
*/
public function getCastedValue() {
return (int) $this->value;
}
}
14. create a typed data object in code
First get the typed_data_manager service from the container or by
calling Drupal::typedDataManager().
Then pass the plugin ID to $manager::createDataDefinition() to
create an appropriate data definition object.
Then pass the data definition object and the value of the data to
$manager::create() to create a typed data object.
15. $definition = DataDefinition::create('integer');
$int = Drupal::typedDataManager()->create($definition);
$int->setValue('10');
$validation = $int->validate();
$raw_data = $int->getValue();
$int_data = $int->getCastedValue();
$raw_data_type = gettype($raw_data);
$int_data_type = gettype($int_data);
Integer data type usage example
16.
17. Constraints
The Data Definition class can set constraints upon the Typed Data
object.
Constraint plugins:
core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint
Symfony constraints:
docroot/vendor/symfony/validator/Constraints
22. List data types represent data that is an ordered list of typed data, all of
the same type.
More precisely, the plugins in the list must have the same base plugin ID;
however, some types (for example field items and entities) are provided
by plugin derivatives and the sub IDs can be different.
List Data types
24. List data example
$data = [
'1250-5154-6548-6831',
'2233-5154-6648-6843',
'3276-5154-6748-6822',
'4289-5154-6848-6867',
];
$list_definition = ListDataDefinition::create('string');
$credit_cards = Drupal::typedDataManager()->create($list_definition);
$credit_cards->setValue($data);
$validation = $credit_cards->validate();
$first_card = $credit_cards->get(0)->getValue();
foreach ($credit_cards as $card) {
$test[] = $card->getValue();
}
25.
26. Complex Data
Complex data types, with interface
DrupalCoreTypedDataComplexDataInterface, represent data with
named properties.
The properties can be accessed with get() and set() methods. The value
of each property is itself a typed data object, which can be primitive,
complex, or list data.
27. The "map" data type
The "map" data type represent a simple complex data type, e.g. for
representing associative arrays. It can also serve as base class for any
complex data type.
By default there is no metadata for contained properties. Extending
classes may want to override
MapDataDefinition::getPropertyDefinitions() to define it.
28. Defining data types
Create a Definition class that implements one of the Typed Data
interfaces.
Create a DataType plugin that use your Definition class .
To do that, put it in namespace
DrupalyourmodulePluginDataType, and add annotation of type
DrupalCoreTypedDataAnnotationDataType to the
documentation header.
29. <?php
namespace Drupalactivenet_syncTypedDataDefinition;
use DrupalCoreTypedDataComplexDataDefinitionBase;
use DrupalCoreTypedDataDataDefinition;
/**
* ActiveNet Asset Price definition.
*/
class AssetPriceDefinition extends ComplexDataDefinitionBase {
/**
* {@inheritdoc}
*/
public function getPropertyDefinitions() {
if (!isset($this->propertyDefinitions)) {
$info = &$this->propertyDefinitions;
$info['priceType'] = DataDefinition::create('string')->setRequired(TRUE)->setLabel('priceType');
$info['priceAmt'] = DataDefinition::create('float')->setRequired(TRUE)->setLabel('priceAmt');
$info['maxPriceAmt'] = DataDefinition::create('float')->setRequired(TRUE)->setLabel('maxPriceAmt');
$info['minPriceAmt'] = DataDefinition::create('float')->setRequired(TRUE)->setLabel('minPriceAmt');
}
return $this->propertyDefinitions;
}
}
activenet_sync/src/TypedData/Definition/AssetPriceDefinition.php
33. Using data types
In the Field API, data types can be
used as the class in the property
definition of the field.
Describe data defined elsewhere i.e.
schemas from external systems.
In configuration schema files, you can
use the unique ID ('id' annotation)
from any DataType plugin class as the
'type' value for an entry.
paragraphs.paragraphs_type.*:
type: config_entity
label: 'Paragraphs type config'
mapping:
id:
type: string
label: 'ID'
label:
type: label
label: 'Label'