Skip to content

Instantly share code, notes, and snippets.

@zim32
Created August 9, 2022 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zim32/5a8e6c7c2127f7e91863543fda05f39b to your computer and use it in GitHub Desktop.
Save zim32/5a8e6c7c2127f7e91863543fda05f39b to your computer and use it in GitHub Desktop.
Doctrine trait for handling associations
<?php
namespace Zim\Bundle\SymfonyRestHelperBundle\Doctrine;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
trait ORMSetterTrait
{
/**
* @param mixed $data Submitted data (Converted by serialized into doctrine entities)
* @param string $propertyName Inverse property name
* @param string $owningPropertyName Owning property name
* @param callable $comparator First argument is submitted item, second argument is existing item
* @param boolean $orphanRemoval Pass true, if you need to delete owning entity. Passing true, prevents calling setter on owning side
*/
protected function handleOneToMany($data, string $propertyName, string $owningPropertyName, callable $comparator, bool $orphanRemoval = false)
{
if (!($data instanceof Collection)) {
$data = new ArrayCollection($data);
}
// handle removing
foreach ($this->{$propertyName} as $existing) {
if (false === $data->exists(function($key, $val) use ($existing, $comparator) {
return $comparator($val, $existing);
})) {
$this->{$propertyName}->removeElement($existing);
$owningSetter = 'set' . ucfirst($owningPropertyName);
if (!$orphanRemoval) {
$existing->$owningSetter(null);
}
}
}
// handle addition
foreach ($data as $newItem) {
if (false === $this->{$propertyName}->exists(function($key, $item) use ($newItem, $comparator) {
return $comparator($newItem, $item);
})) {
$this->{$propertyName}->add($newItem);
$owningSetter = 'set' . ucfirst($owningPropertyName);
$newItem->$owningSetter($this);
}
}
}
/**
* @param mixed $data Submitted data (Converted by serialized into doctrine entities)
* @param string $propertyName Inverse property name
* @param string $owningPropertyName Owning property name
* @param callable $comparator First argument is submitted item, second argument is existing item
*/
protected function handleManyToManyInverseSide($data, string $propertyName, string $owningPropertyName, callable $comparator)
{
if (!($data instanceof Collection)) {
$data = new ArrayCollection($data);
}
// handle removing
foreach ($this->{$propertyName} as $existing) {
if (false === $data->exists(function($key, $val) use ($existing, $comparator) {
return $comparator($val, $existing);
})) {
$this->{$propertyName}->removeElement($existing);
$owningGetter = 'get' . ucfirst($owningPropertyName);
$existing->$owningGetter()->removeElement($this);
}
}
// handle addition
foreach ($data as $newItem) {
if (false === $this->{$propertyName}->exists(function($key, $item) use ($newItem, $comparator) {
return $comparator($newItem, $item);
})) {
$this->{$propertyName}->add($newItem);
$owningGetter = 'get' . ucfirst($owningPropertyName);
$newItem->$owningGetter()->add($this);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment