Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using @Embedded / @Embeddable with Doctrine 2.5 and Unique Constraints

Doctrine 2.5 allows @Embeddable and @Embedded annotations - giving developers the ability to create Entities alongside Value Objects. If you are using composer, as of May 2014, you need to have: "minimum-stability": "dev" in your composer.json to use it.

I have a Server entity, and I'm trying to map an IpAddress value object against this. @Embeddable and @Embedded work great here.

However, I want the Server entity to have a unique constraint on the ipAddress property - which maps to a value object. This would work for a normal property, but for embedded ones, I get an exception when trying to update my schema from my entities:

Doctrine SchemaException - @Embeddable @Embedded

Server Entity

namespace App\Model\Entity;

use App\Model\Entity\ValueObjects\Server\IpAddress,
    Doctrine\ORM\Mapping as ORM;

/**
 * Class Server
 *
 * @ORM\Table(name="servers", uniqueConstraints={@ORM\UniqueConstraint(name="unique_ip_address", columns={"ipAddress"})})
 * @ORM\Entity(repositoryClass="App\Model\Repository\ServerRepository")
 */
class Server
{
   /**
    * @var IpAddress
    *
    * @ORM\Embedded(class="App\Model\Entity\ValueObjects\Server\IpAddress")
    */
    private $ipAddress;
}

IpAddress Value Object

namespace App\Model\Entity\ValueObjects\Server;

use Doctrine\ORM\Mapping as ORM;

/**
 * Class IpAddress
 *
 * @package App\Model\Entity\ValueObjects\Server
 *
 * @ORM\Embeddable
 */
class IpAddress
{
    /**
     * @var string
     *
     *  @ORM\Column(name="ip_address", type="string", length=15, nullable=false)
     */
    private $ipAddress;
}

I presume I am mapping the classes together correctly. How can I place a unique constraint on an embedded object's property? I have tried the . syntax when defining the columns section of uniqueConstraints, but it was a complete guess and naturally failed.

like image 712
Jimbo Avatar asked May 26 '14 10:05

Jimbo


1 Answers

Jimbo's edit: Basically, the answer to this is to remove the UniqueConstraints from the Server object, and place unique directly on the value object property.

Based on your schema output your column name in the index should be ipAddress_ip_address

@ORM\Table(name="servers", uniqueConstraints={@ORM\UniqueConstraint(name="unique_ip_address", columns={"ipAddress_ip_address"})})

Alternatively, if the IP address is unique in all tables it's embedded, then you could place the constraint in the IpAddress class.

/**
 * @var string
 *
 *  @ORM\Column(name="ip_address", type="string", length=15, nullable=false, unique=true)
 */
private $ipAddress;
like image 160
FuzzyTree Avatar answered Oct 17 '22 09:10

FuzzyTree