Hello. Today I'm going to talk about how to create an entity and all related classes for it. This is a very simple tutorial. In case you are looking for something more advanced, please check the documentation.
These are the classes related to entities as well as a brief explanation why they are necessary:
Type | Explanation | Example |
---|---|---|
Entity | This is the representation of the entity itself | Book Person Car |
EntityDefinition | This class definines types of database columns, setup of entity name, hydrator, collection, default values... etc | BookDefinition PersonDefinition CarDefinition |
EntityHydrator | This class populates the data coming from the database (or other storages like in-memory, external services, CSV...) | BookHydrator PersonHydrator CarHydrator |
EntityCollection | This class makes working with a list of entities in a elegant way like custom filters and getters instead of primitive arrays | BookCollection PersonCollection CarCollection |
It's important to understand what domain your entity is related to. There are few domains that your entity might be part of, however if you are creating a general entity it should be put on Content
domain. These are other possible domains: Checkout
, Framework
and System
.
So, in the root of your plugin, please create the directory src/Content
, so we will put the PHP files there.
services.xml
Definition and hydrator classes should be injected in your plugin: src/Resources/config/services.xml
:
<service id="MatheusGontijo\HelloWorld\Content\Speaker\SpeakerDefinition">
<tag name="shopware.entity.definition" entity="matheusgontijo_speaker" />
</service>
<service id="MatheusGontijo\HelloWorld\Content\Speaker\SpeakerHydrator" public="true">
<argument type="service" id="service_container" />
</service>
We will have three attributes: id
, name
and nationality
. The attributes created at
and updated at
are being handled by Shopware itself. Please create the SpeakerEntity.php
file on Content
directory:
<?php declare(strict_types=1);
namespace MatheusGontijo\HelloWorld\Content\Speaker;
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityIdTrait;
class SpeakerEntity extends Entity
{
use EntityIdTrait;
/**
* @var string|null
*/
protected $name;
/**
* @var string|null
*/
protected $nationality;
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): void
{
$this->name = $name;
}
public function getNationality(): ?string
{
return $this->nationality;
}
public function setNationality(?string $nationality): void
{
$this->nationality = $nationality;
}
}
Create the SpeakerDefinition.php
file:
<?php declare(strict_types=1);
namespace MatheusGontijo\HelloWorld\Content\Speaker;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\ApiAware;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\PrimaryKey;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required;
use Shopware\Core\Framework\DataAbstractionLayer\Field\IdField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;
class SpeakerDefinition extends EntityDefinition
{
public const ENTITY_NAME = 'matheusgontijo_speaker';
public function getEntityName(): string
{
return self::ENTITY_NAME;
}
public function getCollectionClass(): string
{
return SpeakerCollection::class;
}
public function getEntityClass(): string
{
return SpeakerEntity::class;
}
public function getHydratorClass(): string
{
return SpeakerHydrator::class;
}
protected function defineFields(): FieldCollection
{
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new ApiAware(), new PrimaryKey(), new Required()),
(new StringField('name', 'name'))->addFlags(new ApiAware(), new Required()),
(new StringField('nationality', 'nationality'))->addFlags(new ApiAware(), new Required()),
]);
}
}
Create the SpeakerHydrator.php
file:
<?php declare(strict_types=1);
namespace MatheusGontijo\HelloWorld\Content\Speaker;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityHydrator;
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\Uuid\Uuid;
use DateTimeImmutable;
class SpeakerHydrator extends EntityHydrator
{
protected function assign(EntityDefinition $definition, Entity $entity, string $root, array $row, Context $context): Entity
{
if (isset($row[$root . '.id'])) {
$entity->id = Uuid::fromBytesToHex($row[$root . '.id']);
}
if (isset($row[$root . '.name'])) {
$entity->name = $row[$root . '.name'];
}
if (isset($row[$root . '.nationality'])) {
$entity->nationality = $row[$root . '.nationality'];
}
if (isset($row[$root . '.createdAt'])) {
$entity->createdAt = new DateTimeImmutable($row[$root . '.createdAt']);
}
if (isset($row[$root . '.updatedAt'])) {
$entity->updatedAt = new DateTimeImmutable($row[$root . '.updatedAt']);
}
return $entity;
}
}
Create the SpeakerCollection.php
file:
<?php declare(strict_types=1);
namespace MatheusGontijo\HelloWorld\Content\Speaker;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
/**
* @method void add(SpeakerEntity $entity)
* @method void set(string $key, SpeakerEntity $entity)
* @method SpeakerEntity[] getIterator()
* @method SpeakerEntity[] getElements()
* @method SpeakerEntity|null get(string $key)
* @method SpeakerEntity|null first()
* @method SpeakerEntity|null last()
*/
class SpeakerCollection extends EntityCollection
{
public function getApiAlias(): string
{
return 'matheusgontijo_speaker_collection';
}
protected function getExpectedClass(): string
{
return SpeakerEntity::class;
}
}
Great! We created our Speaker
entity and all entity related classes! This is how the structure should look like in the end:
MatheusGontijoHelloWorld
└── src
└── Content
└── Speaker
├── SpeakerCollection.php
├── SpeakerDefinition.php
├── SpeakerEntity.php
└── SpeakerHydrator.php
Thank you! In the next blogpost, let's create a repository to write and read data to make sure it's all working.