Last active
September 12, 2018 09:37
-
-
Save Itach1Uchixa/83fedd850e4705b0b51589afaefdfdf1 to your computer and use it in GitHub Desktop.
Custom collections with doctrine 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// clean but complex way | |
namespace YourDomain\Entities | |
{ | |
use Doctrine\Common\Collections\Collection as DoctrineCollection; | |
/** @MappedSuperclass */ | |
class SomeEntity | |
{ | |
/** | |
* @var CustomCollectionInterface | |
* @OneToManyWhatever(doctrineAnnotationCode) | |
*/ | |
protected $customCollection; | |
// keep in mind: further in code we will access to collection using this accessor | |
protected function getCustomCollection(): CustomCollection | |
{ | |
return $this->customCollection; | |
} | |
} | |
interface CustomCollectionInterface | |
{ | |
// collection methods ... | |
} | |
} | |
namespace YourDomain\Infrastructure\ORM\Doctrine | |
{ | |
use YourDomain\Entities\CustomCollectionInterface; | |
use Doctrine\Common\Collections\Collection as DoctrineCollection; | |
// the idea is repository will return this entity | |
// only when inserting we will have to replace our domain's SomeEntity to this entity | |
class SomeEntityProxy extends SomeEntity | |
{ | |
/** | |
* @var DoctrineImplOfCustomCollection | |
*/ | |
protected $customCollectionCache; | |
// little override | |
protected function getCustomCollection(): CustomCollection | |
{ | |
if (is_null($this->customCollectionCache) && $this->customCollection instanceof DoctrineCollection) { | |
$this->customCollectionCache = new DoctrineImplOfCustomCollection($this->customCollection); | |
} | |
return $this->customCollectionCache ?? parent::getCustomCollection(); | |
} | |
} | |
class DoctrineImplOfCustomCollection implements CustomCollectionInterface | |
{ | |
/** | |
* @var DoctrineCollection | |
*/ | |
protected $items; | |
public function __construct(DoctrineCollection $collection) | |
{ | |
// as we will work with reference it will not load all items | |
$this->items = $collection; | |
} | |
// collection methods ... | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// simple way of using custon collection with doctrine 2 | |
use Doctrine\Common\Collections\Collection as DoctrineCollection; | |
class SomeEntity | |
{ | |
/** | |
* @var CustomCollection | |
* @OneToManyWhatever(doctrineAnnotationCode) | |
*/ | |
protected $customCollection; | |
/** | |
* @var CustomCollection | |
*/ | |
protected $customCollectionCache; | |
// keep in mind: further in code we will access to collection using this accessor | |
protected function getCustomCollection(): CustomCollection | |
{ | |
if (is_null($this->customCollectionCache) && $this->customCollection instanceof DoctrineCollection) { | |
$this->customCollectionCache = CustomCollection::fromCollection($this->customCollection); | |
} | |
return $this->customCollectionCache ?? $this->customCollection; | |
} | |
} | |
class CustomCollection | |
{ | |
/** | |
* @var Item[] | |
*/ | |
protected $items; | |
public function __construct(Item ...$items) | |
{ | |
$this->items = $items; | |
} | |
public static function fromCollection(DoctrineCollection $collection): self | |
{ | |
$instance = new static(); | |
// our custom collection will reference doctrine's for updates to work | |
// now you can add, remove items from array and updates will be persisted | |
// we can use our collection's items property as simple array | |
// because doctrine's collection is array accessable (isset and etc. functions will work) | |
// if you need more than just generic array functions then read clean_but_complex.php file in this gist | |
$instance->items = $collection; | |
return $instance; | |
} | |
// collection logic ... | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The simple method is close to my approach https://gist.github.com/Arkemlar/d1dca641e9f6932d37d052af3265a71d
(Sinсe I published this gist I found some bugs/stupid code, but had lack of time to transfer fixes from project code to gist.)
The complex metod seems wierd - overcomplicated and not reliable since Doctrine always will return its own proxy instances (like in case of loading entities through *ToMany relations using collection).