Skip to main content

Adding an entity reference to a Sulu entity

This blog post might be outdated!
This blog post was published more than one year ago and might be outdated!
· 3 min read
Stephan Hochdörfer
Head of IT Business Operations

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!