This example shows us how we create one-to-one composition relationship with Doctrine and Symfony.


Notes



Design




Mapping


Continent


declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="continent")
*/
class Continent
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
* @ORM\Column(name="name", type="string", length=100, nullable=false)
*/
private $name;

/**
* @ORM\OneToOne(targetEntity="Country", mappedBy="continent", cascade={"persist", "remove"})
*/
private $country;

public function getId(): int
{
return $this->id;
}

public function setName(string $name): self
{
$this->name = $name;

return $this;
}

public function getName(): string
{
return $this->name;
}

public function getCountry(): Country
{
return $this->country;
}

public function setCountry(Country $country): self
{
$this->country = $country;

return $this;
}
}

Country


declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="country", uniqueConstraints={@ORM\UniqueConstraint(columns={"name"})})
*/
class Country
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
* @ORM\Column(name="name", type="string", length=100, nullable=false)
*/
private $name;

/**
* @ORM\OneToOne(targetEntity="Continent", inversedBy="country", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="continent_id", referencedColumnName="id", nullable=false)
*/
private $continent;

public function getId(): int
{
return $this->id;
}

public function setName(string $name): self
{
$this->name = $name;

return $this;
}

public function getName(): string
{
return $this->name;
}

public function getContinent(): Continent
{
return $this->continent;
}

public function setContinent(Continent $continent): self
{
$this->continent = $continent;

return $this;
}
}

Database


CREATE TABLE `continent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `country` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`continent_id` int(11) NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_5373C966921F4C77` (`continent_id`),
UNIQUE KEY `UNIQ_5373C9665E237E06` (`name`),
CONSTRAINT `FK_5373C966921F4C77` FOREIGN KEY (`continent_id`) REFERENCES `continent` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Test


Creating a new Continent and a new Country at same time.


$continent = new Continent();
$continent->setName('Africa');

$country = new Country();
$country->setName('Gana');

$country->setContinent($continent);
$continent->setCountry($country);

// You can use both of them at same time but using one over another is more logical as cascade={"persist"} will handle it for us.
$this->entityManager->persist($continent);
$this->entityManager->persist($country);
//

$this->entityManager->flush();