lenny4 / doctrine-merge-persistent-collection-bundle
Merge persistence collection when update entity
Fund package maintenance!
Lenny4
Installs: 892
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: ^8.1
- doctrine/orm: ^2.13
- symfony/config: ^6.1
- symfony/dependency-injection: ^6.1
- symfony/http-kernel: ^6.1
Requires (Dev)
- api-platform/core: ^3.2
- dama/doctrine-test-bundle: ^7.1
- doctrine/doctrine-bundle: ^2.7
- doctrine/doctrine-fixtures-bundle: ^3.4
- doctrine/doctrine-migrations-bundle: ^3.2
- nelmio/cors-bundle: ^2.2
- phpdocumentor/reflection-docblock: ^5.3
- phpstan/phpdoc-parser: ^1.7
- phpunit/phpunit: ^10
- rector/rector: dev-main
- roave/security-advisories: dev-latest
- symfony/asset: ^6.1
- symfony/browser-kit: ^6.1
- symfony/css-selector: ^6.1
- symfony/dotenv: ^6.1
- symfony/expression-language: ^6.1
- symfony/flex: ^2.2
- symfony/framework-bundle: ^6.1
- symfony/http-client: ^6.1
- symfony/maker-bundle: ^1.45
- symfony/phpunit-bridge: ^6.1
- symfony/property-access: ^6.1
- symfony/property-info: ^6.1
- symfony/proxy-manager-bridge: ^6.1
- symfony/runtime: ^6.1
- symfony/security-bundle: ^6.1
- symfony/serializer: ^6.1
- symfony/twig-bundle: ^6.1
- symfony/validator: ^6.1
- symfony/yaml: ^6.1
Conflicts
README
Merge persistence collection when update entity
This bundle is very usefull if you are using ApiPlatform and you don't want to send multiple requests when you update an entity and his children.
Installation
You can install the package via composer:
composer require lenny4/doctrine-merge-persistent-collection-bundle
Usage
<?php namespace App\Controller; use Lenny4\DoctrineMergePersistentCollectionBundle\DoctrineMergePersistentCollection; use Lenny4\DoctrineMergePersistentCollectionBundle\Entity\Father; use Lenny4\DoctrineMergePersistentCollectionBundle\Entity\Son; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class PutFatherController extends AbstractController { public function __invoke(Father $data, DoctrineMergePersistentCollection $doctrineMergePersistentCollection): Father { $doctrineMergePersistentCollection->merge( $data->getSons(), static function (Son $son1, Son $son2) { return $son1->getName() === $son2->getName(); }, static function (Son $son1, Son $son2) { $son1->setAge($son2->getAge()); }, ); return $data; } }
How does it work ?
Let's say you have 2 entities Father
and Son
as ApiResource
#[ApiResource( collectionOperations: [ 'get', ], itemOperations: [ 'get', 'put' => [ 'controller' => PutFatherController::class, ], ], attributes: [ 'denormalization_context' => ['groups' => ['w-father']], ], )] #[ORM\Entity(repositoryClass: FatherRepository::class)] class Father { #[ORM\Column] #[ORM\GeneratedValue] #[ORM\Id] private ?int $id = null; #[ORM\Column(length: 255)] #[Groups(['w-father'])] private ?string $name = null; /** * @var Collection<int, Son>|Son[] */ #[ORM\OneToMany(mappedBy: 'father', targetEntity: Son::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[Groups(['w-father'])] private Collection $sons; // getters setters }
#[ApiResource()] #[ORM\Entity(repositoryClass: SonRepository::class)] class Son { #[ORM\Column] #[ORM\GeneratedValue] #[ORM\Id] private ?int $id = null; #[ORM\Column(length: 255)] #[Groups(['w-father'])] private ?string $name = null; #[ORM\Column] #[Groups(['w-father'])] private ?int $age = null; #[ORM\JoinColumn(nullable: false)] #[ORM\ManyToOne(inversedBy: 'sons')] private ?Father $father = null; // getters setters }
With these data in your database:
Let's say you want to update the name of the Father
from father1
to father2
and the age of 1 of his
children son1
only with 1 request. It's currently impossible only
with ApiPlatform. But with this Bundle you can do it now by
calling doctrineMergePersistentCollection->merge
as shown in the Usage.
- The first argument of the function take a
PersistentCollection
which correspond to all the sons of the father - The second argument is a callable which define how 2 sons are the same (in our example it's the
name
$son1->getName() === $son2->getName()
) - The second argument is a callable which define how to update a son if
$son1->getName() === $son2->getName()
return true;
Use case (example)
- Add a son
PUT /api/fathers/1
{ "name": "father2", "sons": [ { "name": "son1", "age": 10 }, { "name": "son2", "age": 20 }, { "name": "son3", "age": 30 } ] }
This will change the name of the father to father2
and add a son. Result:
- Update son2 age
PUT /api/fathers/1
{ "name": "father2", "sons": [ { "name": "son1", "age": 10 }, { "name": "son2", "age": 30 } ] }
This will change the name of the father to father2
and son2 age. Result:
Testing
docker-compose up
./runc composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
License
The MIT License (MIT). Please see License File for more information.