Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

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();