Adding an entity reference to a Sulu entity
Let's assume you have a sulu entity App\Entity\MyEntity
defined and you want to add a reference to this other entity
App\Entity\OtherEntity
to it. Follow this blog post along to find out which steps you have to take.
First, let's add the property to the App\Entity\MyEntity
entity which holds the reference to the App\Entity\OtherEntity
entity.
We will call this property "other":
#[ORM\ManyToOne(targetEntity: \App\Entity\OtherEntity::class)]
#[ORM\JoinColumn(onDelete: 'SET NULL')]
private ?\App\Entity\OtherEntity $other = null;
Additionally, we also have to define the getter and setter methods for the "other" property:
public function getOther(): ?\App\Entity\OtherEntity
{
return $this->Other;
}
public function setOther(\App\Entity\OtherEntity $other): self
{
$this->other = $other;
return $this;
}
To be able to reference a custom selector for the App\Entity\OtherEntity
entity in the form view, we first have to declare
a new selection type in the file config/packages/sulu_admin.yaml
by adding the following lines:
sulu_admin:
# Registering Selection Field Types in this section
field_type_options:
single_selection:
single_otherentity_selection:
default_type: list_overlay
resource_key: otherentity
types:
list_overlay:
adapter: table
list_key: otherentity
display_properties:
- name
icon: fa-home
empty_text: 'app.other_entity.no_selections'
overlay_title: 'app.other_entity'
For the resource_key
and list_key
pick the names you have already defined. Via the display_properties
you can define
the properties that should be displayed in the UI to allow the content editor to pick the entity.
This is all it needs to let Sulu understand that a new property type single_otherentity_selection
exists which can now
be used in the form xml structure to define the property for selecting the App\Entity\OtherEntity
entity:
<property name="otherId" type="single_otherentity_selection" mandatory="true">
<meta>
<title>app.other_entity</title>
</meta>
</property>
Next, we need to make sure the Admin API responses contain all the needed data so that the Sulu Admin interface is able
to properly render everything. Following the code in the sulu-workshop repository,
my Admin controller has a getDataForEntity()
method as well as a mapDataToEntity()
method which both need to be adapted.
In the mapDataToEntity()
method, we need to fetch the Doctrine entity for the otherId
and pass the fetched entity
to the App\Entity\MyEntity
entity. To be able to access \App\Repository\OtherRepository
it needs to be injected via
the constructor of the Admin controller class:
protected function mapDataToEntity(array $data, \App\Entity\MyEntity $entity): void
{
/** @var \App\Repository\OtherRepository $this->otherRepository */
$otherEntity = $data['otherId'] ? $this->otherRepository->findById((int) $data['otherId']) : null
$entity->setOther($otherEntity);
$entity->setName($data['name']);
}
The getDataForEntity()
method is called by every method in the Admin controller which returns the entity information
back to the Sulu Admin UI. Since we there need otherId
populated with the primary key of the App\Entity\OtherEntity
,
the code looks like this:
protected function getDataForEntity(\App\Entity\MyEntity $entity): array
{
$otherEntity = $entity->getOther();
return [
'id' => $entity->getId(),
'otherId' => (null !== $otherEntity) ? $otherEntity->getId() : null,
'name' => $entity->getName() ?? '',
];
}
Last, but not least, we want to display the other reference also in the list overview. For this, the xml configuration needs
to be extended with the snippet below. Given that App\Entity\OtherEntity
contains a property name
that we want to
display, the property configuration for the list overview needs to look like this:
<property name="otherId" visibility="always" translation="app.other_entity" sortable="false">
<field-name>name</field-name>
<entity-name>App\Entity\OtherEntity</entity-name>
<joins>
<join>
<entity-name>App\Entity\OtherEntity</entity-name>
<field-name>App\Entity\MyEntity.other</field-name>
</join>
</joins>
</property>
If you have a specific Sulu question, join us in the Sulu slack, it is a great resource for all the things Sulu and the Sulu core developers are usually very responsive to answer all the questions!