AbstractEntityAttribute
The Zikula\Bundle\CoreBundle\Doctrine\Entity\AbstractEntityAttribute
class provides a base class for implementing attribute support
for your entities.
Preconditions
You need a existing Doctrine entity to which you would like add attributes support to. In this guide we will use a User entity::
namespace Acme\YourModule\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zikula\Bundle\CoreBundle\Doctrine\EntityAccess;
/**
* @ORM\Entity
* @ORM\Table(name="yourmodule_user")
*/
class UserEntity extends EntityAccess
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(length=30)
*/
private $username;
/**
* @ORM\Column(length=30)
*/
private $password;
// getter and setter
}
Entities
The core bundle provides the following abstract class: Zikula\Bundle\CoreBundle\Doctrine\Entity\AbstractEntityAttribute
.
You need to create a subclass of that class specific to the entity you would like
to add attributes support to. In this guide we create a UserAttributeEntity
class.
UserEntity is the name of the entity and Attribute is our attributes specific suffix:
namespace Acme\YourModule\Entity;
use Acme\YourModule\Entity\UserEntity;
use Doctrine\ORM\Mapping as ORM;
use Zikula\Bundle\CoreBundle\Doctrine\EntityAccess;
use Zikula\Bundle\CoreBundle\Doctrine\Entity\AbstractEntityAttribute;
/**
* @ORM\Entity
* @ORM\Table(name="yourmodule_user_attribute",
* uniqueConstraints={@ORM\UniqueConstraint(name="cat_unq",columns={"name", "entityId"})})
*/
class UserAttributeEntity extends AbstractEntityAttribute
{
/**
* @ORM\ManyToOne(targetEntity="Acme\YourModule\Entity\UserEntity", inversedBy="attributes")
* @ORM\JoinColumn(name="entityId", referencedColumnName="id")
* @var UserEntity
*/
private $entity;
public function getEntity()
{
return $this->entity;
}
public function setEntity($entity)
{
$this->entity = $entity;
}
}
The abstract class forces you to implement the getEntity and setEntity methods.
These methods force you to create an new class attribute.
This attribute becomes a ManyToOne association to the original UserEntity
.
The column name "entityId" in @JoinColumn
and @UniqueConstraint
must match.
We need to add a inverse side of the association to the original UserEntity
use Acme\YourModule\Entity\UserAttributeEntity;
use Doctrine\Common\Collections\ArrayCollection;
// …
/**
* @ORM\OneToMany(targetEntity="Acme\YourModule\Entity\UserAttributeEntity",
* mappedBy="entity", cascade={"all"},
* orphanRemoval=true, indexBy="name")
*/
private $attributes;
public function __construct()
{
$this->attributes = new ArrayCollection();
}
public function getAttributes()
{
return $this->attributes;
}
public function setAttribute($name, $value)
{
if (isset($this->attributes[$name])) {
if (null === $value) {
$this->attributes->remove($name);
} else {
$this->attributes[$name]->setValue($value);
}
} else {
$this->attributes[$name] = new UserAttributeEntity($name, $value, $this);
}
}
The inversedBy
attribute of the @ManyToOne
annotation must match with this new class attribute name.
The mappedBy
attribute of the @OneToMany
annotation must match with the class attribute in
the AbstractEntityAttribute
subclass.
Install code
List your AbstractEntityAttribute
subclass in the $this->schemaTool->create()
method call.
Working with the entities
Set/change an attribute:
$user = // …
$user->setAttribute('url', 'https://www.example.com');
$entityManager->persist($user);
Remove an attribute:
$user = // …
$user->setAttribute('url', null);
$entityManager->persist($user);
Access all attributes:
$user = // …
$urlValue = $user->getAttributes()->get('url')->getValue();