php-ddd icon indicating copy to clipboard operation
php-ddd copied to clipboard

Doctrine (Array)Collection and other equivalents to Java (Array)List

Open webdevilopers opened this issue 9 years ago • 1 comments

When reading my first DDD Java examples I saw a lot of Lists:

class Order
{
    private Integer ID;
    private Customer owner;
    private List<Product> ordered;

A List is an interface like Set and has ArrayList as stated by @iamzero

  • http://stackoverflow.com/a/30973050/1937050 and extends Collection as stated by @brendanlong
  • http://stackoverflow.com/a/7762801/1937050

Unfortunately PHP does not have a true equivalent as @giorgiosironi knows:

  • https://dzone.com/articles/5-things-php-envies-java and @fkling explains:
  • http://stackoverflow.com/a/4570729/1937050

But we have @doctrine Collections:

  • https://github.com/doctrine/collections/blob/master/lib/Doctrine/Common/Collections/ArrayCollection.php

And alternatives like Ardent by @morrisonlevi:

  • https://github.com/morrisonlevi/Ardent

The docs say:

An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.

  • http://docs.oracle.com/javase/7/docs/api/java/util/List.html

When using @doctrine ArrayCollections you can use the indexBy mapping to make your Collection indexed (ordered):

Doctrine 2 collections are modelled after PHPs native arrays. PHP arrays are an ordered hashmap, but in the first version of Doctrine keys retrieved from the database were always numerical unless INDEX BY was used. You have to manage both the key and field if you want to change the index by field value.

  • http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/working-with-indexed-associations.html

But you have to be careful when using accessors as @MacDada warns:

  • https://github.com/webdevilopers/php-ddd/issues/13#issuecomment-223530323

Still it seems to be a matter of taste if you use ArrayCollection at all in your Domain Models:

Don't be alarmed by the use of ArrayCollections. Notice that is in the Doctrine/Common namespace. It's just a little utility array wrapper with no particular ties to the Doctrine persistence layer. You could easily replace it with another array class.

  • http://stackoverflow.com/a/18474456/1937050 @koryonik

@tPl0ch warns:

The problem with Doctrine collections and the ORM is that you cannot use custom Collection implementations since you will always receive a PersistenCollection in your proxies.

  • http://stackoverflow.com/a/29552486/1937050 @dermo666

What are your thoughts? Any use cases? Any comparison to the Java DDD approaches using List?

webdevilopers avatar Sep 26 '16 15:09 webdevilopers

I also recognized @yvoyer using the term Collection for InMemory Repositories:

  • https://github.com/webdevilopers/php-ddd/blob/aba5cd51cbed93416f7eed02ebc3110ab7b736af/src/Infrastructure/InMemory/OwnerCollection.php

If someone used Doctrine (ArrayCollections) throughout his project it could be used as a PHP wrapper - analog to the Java (Array)List) - and return it (like Doctrine Repositories do using default hydration):

final class OwnerCollection implements OwnerRepository, \Countable
{
    /**
     * @var ArrayCollection Owner[]
     */
    private $owners = [];

    /**
     * @param OwnerId $ownerId
     *
     * @throws EntityNotFoundException
     * @return Owner
     */
    public function ownerWithId(OwnerId $ownerId)
    {
        if (! isset($this->owners[$ownerId->id()])) {
            throw EntityNotFoundException::entityWithIdentity($ownerId);
        }
        return $this->owners[$ownerId->id()];
    }

Analog to Java:

public List<Order> findAllMatching(Criteria someCriteria)
{
    ResultSet rcds = this.db.execFindOrdersQueryWith(someCriteria.toString());
    List<List<String>> results = convertToStringList(rcds);

    List<Order> returnList = new ArrayList<Order>();

    for(List<String> row : results)
        returnList.add(this.orderFactory.createFrom(row));

    return returnList;
}
  • http://stackoverflow.com/a/571819/1937050

webdevilopers avatar Sep 26 '16 15:09 webdevilopers