I'm creating a folder structure implemented with the NestedTree behaviour.
Furthermore, I don't want that two folders may have the same name if they are siblings.
For this, I use the combination of @UniqueEntity
and @UniqueConstraint
annotations, but it does not work.
First my entity (stripped to the minimum since it is 100% identical to the NestedTree defaults) :
/**
* @ORM\Entity
* @Gedmo\Tree(type="nested")
* @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
* @UniqueEntity(fields={"parent", "name"})
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="uniq_url", columns={"parent_id", "name"})})
*/
class Folder
{
/**
* @ORM\Column(type="string", nullable=false)
*/
protected $name;
/**
* @Gedmo\TreeParent
* @ORM\ManyToOne(targetEntity="Folder", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $parent;
}
First try (ignoreNull = true)
When I create two folders with the same name, I have an integrity constraint violation, meaning that the @UniqueConstraints
in the database worked but that the @UniqueEntity
didn't :
Integrity constraint violation: 1062 Duplicate entry 'name_of_folder' for key 'uniq_url'
Second try (ignoreNull = false)
I also tried with the ignoreNull key set to false (the default is true) :
@UniqueEntity(fields={"parent", "name"}, ignoreNull=false)
but then I get this error :
Warning: ReflectionProperty::getValue() expects parameter 1 to be object, null given in vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php line 670
I've nailed the error down to these lines in Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator
:
$criteria[$fieldName] = $class->reflFields[$fieldName]->getValue($entity);
if ($constraint->ignoreNull && null === $criteria[$fieldName]) {
return;
}
if ($class->hasAssociation($fieldName)) {
/* Ensure the Proxy is initialized before using reflection to
* read its identifiers. This is necessary because the wrapped
* getter methods in the Proxy are being bypassed.
*/
$em->initializeObject($criteria[$fieldName]);
$relatedClass = $em->getClassMetadata($class->getAssociationTargetClass($fieldName));
//problem
$relatedId = $relatedClass->getIdentifierValues($criteria[$fieldName]);
if (count($relatedId) > 1) {
throw new ConstraintDefinitionException(
"Associated entities are not allowed to have more than one identifier field to be " .
"part of a unique constraint in: " . $class->getName() . "#" . $fieldName
);
}
$criteria[$fieldName] = array_pop($relatedId);
}
The problem appears on the line marked with //problem
. It appears that $criteria[$fieldName] === null
is the reason of the error.
So here I am, not knowing what to do... Does anybody have an idea on what's going on ?
Thank you.