Fetch associated entities collection from Doctrine2 repository as an array - php

I'm starting a little project with DDD approach. I've created my domain model with Entities and ValueObjects in plain PHP. Entities have references to their associations - in my case, there is an Employee entity with collection of Teams he belongs to, and I keep them in Employee::teams property. Everything is going great, I've created mappings for those entities with associations in YAML, interfaces for repositories to be implemented in the Symfony2 and Doctrine2 layer, etc.
When I fetch Employees from repository (with Doctrine's EntityManager::findAll()) instead of array of Teams I receive PersistentCollection with those teams. It's built on PHP7, and Employee::getTeams() has return type of array so I'm getting the critical exception.
Is there any way to convert it into array with some external listeners (Symfony layer only, to not to mess in domain files) or any other core mechanism?
Thanks.

You get ArrayCollection
http://www.doctrine-project.org/api/common/2.5/class-Doctrine.Common.Collections.ArrayCollection.html
It has toArray() method so you can write
/**
* #return Team[]
*/
public function getTeams(): array
{
return $this->teams->toArray();
}
But I prefer
/**
* #return Team[]|ArrayCollection
*/
public function getTeams()
{
return $this->teams;
}
If you use good IDE like PhpStorm it will understand it correctly to autocomplete it like ArrayCollection and as Team if you make foreach ($employee->getTeams() as $team) {...
ArrayCollection are more powerful than plain arrays. For example you can filter and order them and Doctrine will make optimized SQL so you don't have to load all items
http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#filtering-collections

Kuba,
That doesn't seem to be a DDD question but a technical question regarding PHP implementation details.
However, please let me jump into your design and try to find a better solution for your domain. You are missing to model the relation between an employee and a team, let's call it employee in team. The way you did you are forcing an AR to reference another AR, saying this way that employee manages a team life cycle. This might not be the case but under a specific scenario another actor might change a status of a team and that could break the Employee invariant over the Team AR. Because of this when you make an AR to manage another AR life cycle then this dependency shouldn't be found through the repository and the root of the aggregate is in the position to now force invariant around the aggregated AR.
There are still some concerns to mention, but just to keep it simple, go ahead and model the concept you are missing: EmployeeInTeam or whatever you want to call it. It references the conceptual identity of the employee and the team so you can remove it safely in a future, you can query employees in a team and teams an employee is part of.
If you need frameworks or the DB to keep the consistence then you are not doing DDD. Use just objects, not the technology.
Regards,
Sebastian.

Related

What is the best way to dynamically set a linked property with just their FK

I've got an entity with a lot of linked properties, when I'm handling a CSV import, I don't want to create $em->getReference() calls for all the linked fields (mainly because i want to keep it as abstract as possible and don't want to hard code all the possible references).
I rather want to do this in the Entity setter method for the given properties. However that would require me to access doctrine from within the Model which in its turn is a bad practice.
Should i access the entity's Metadata and go from there or is there a better approach to this, which I haven't yet mentioned?
Doing it in the setter, really messes up the whole SOA thing. If you care about the code being decoupled and abstract you can use Dependency Inversion.
Let's say you have entity A that has associations to entity B and C, then for getting the references to correct B and C instances from the raw data you get from the CSV, you would define two interfaces e.g: BRepositoryInterface and CRepositoryInterface, they both might contain a single method find($id), but they still have to be distinct. Now make your Doctrine Repositories for the respective entities implement these interfaces and inject them into the service where create entity A.
If you really wanna make some good code, then you should create separate classes implementing each of these interfaces, and then inject your Doctrine Repositories into them, these classes then act as wrappers for those repositories, this way you have a distinct layer between your DataMapper layer and your business logic layer, which gives you the abstraction you want.
This is what I've learned in my recent studies on good code, DDD and Design patterns. It is no where near perfect(not that there is such a thing). Any Ideas/Comments would be appreciated.
Update: In regards to your comment:
One of the main things that good design strives for is "capturing the language of domain experts", (see this source item no.4 for a description of these legendary beings).i.e: What is your code in plain English?
What your code says is basically find the Objects with these given ids from the repositories of the Entities that have an association to A.This looks pretty good since you have no explicit dependencies on what A has associations to.But looking at it closer, you'll see that you do have dependencies on actual B and C Objects and their repositories, since when you provide an id for some Object, you're not just providing an id, but you're also implicitly stating what that object is, otherwise an id would have no meaning other than it's scalar Value.However that approach definitely has it's use cases both in Semantics of the Design, and RAD.But there is still the issue of Law of Demeter, but it can be solved, see below:
Either way I think you should definitely have a factory for A objects that looks something like this.
class AFactory{
protected $br;
protected $cr;
public function __construct(BRepositoryInterface $br, CrepositoryInterface $cr){
$this->br = $br;
$this->cr = $cr;
}
public function create($atr1, $atr2, $bId, $cId){
$b = $this->br->find($bId);
$c = $this->cr->find($cId);
return new A($atr1, $atr2, $bId, $cId);
}
}
Now you can actually create this factory using the design you stated by having another factory for this factory, this will also solve the issue with Law of Demeter.That Factory will have the Entity Manager as it's dependency, it will read A's metadata, and fetch the Repositories of the related objects based on that metadata, and create a new AFactory Instance from those repositories, now if you implement those interfaces (BRepositoryInterface and CRepositoryInterface) in your actual Doctrine Repositories, the AFactory instance will be successfully created.

Where to put traversing graph query in DDD while avoiding doing hundreds of smaller ones?

So I've been trying to make a bit of DDD at the project I work on, but I'm facing the problem I mention in the title.
We have the Entity.php generated by the Symfony console, with the Doctrine annotations in there (I know it is not how it should be made), and the corresponding EntityRepository.php.
The applicable object graph is:
Post entity contains a Messages collection, which in turn have a ReadMessagescollection because we need to know by whom has it been read. To know whether a Post has been read, we want to left join Messages with ReadMessages filtering by the user we need, and if there are any blank ReadMessages, we'll know it has not been read.
If we use a method in the Post entity to iterate over all Messages and all ReadMessages for each of those, Doctrine will be making lots of queries unless we configure the associations as Eager, which we don't want to because then it will be retrieving the associations all the times we ask for a Post; the ideal way would be to use a DQL query that loads the joined entities, but since there is no way to access the repository from the entity (apart from injecting one in the other -which I don't even know if is possible-), I think the only option left is to use a Symfony2 service that gets Doctrine injected. The thing is that I don't really like having to add another piece just as a helper.
Is there any other way to do this?
Thanks in advance.
What if you would filter your collection using criteria (Doctrine\Common\Collections\Criteria)? I think this might solve your problem. You can read on how to do this in detail in the Doctrine2 documentation in 8.8.
It is as simple as you define your Criteria as where message is read and then you get the filtered result as follows:
/**
* Get all read messages
*
* #return Collection
*/
public function getReadMessages(){
$isReadCriteria = //... define criteria
$messages = $this->getMessages();
$readMessages = $messages->matching($isReadCriteria);
return $readMessages;
}

Doctrine Performance On OneToMany RelationShip

I am wondering whether OneToMany Realationship will hamper on application's performance. Say, city and user entity are in a OneToMany relationship, that means, a city can contain a lots of users. Now after setting the relationship in entity classes, whenever I retrieve a city, I can get its users via:
$users = $city->getUsers();
Now, I am wondering about the internal architechture. Whenever I retrieve city, will it query for all users also? If so, lets say a city can have 10000 users. Now won't it be a performance issue that I am retrieving a city only, but its getting along with all 10000 users as well? Or, it uses some other machanism and I am totally ok with it to implement?
Wish to get an explanation from you experts and suggestions about best practices regarding this situations as well. Thanks in advance.
Well, I am not an expert, but I can share you some good practices that you could consider at application development:
fetch="EXTRA_LAZY"
By default, doctrine 2.0 will load the entire collection and store it memory. In a scenario like yours, the users collection could be a performance problems by the table dimesion. So, why not mark the relationship as EXTRA_LAZY? An entity with this fetch mode only will be load when is accessed without triggering a full load of the collection.
/**
* #ManyToMany(targetEntity="User", mappedBy="cities", fetch="EXTRA_LAZY")
*/
Allowing this fetch mode, you are able to make use of function like slide() and count() robustly. For example:
$users = $em->getRepository('models\User')->findAll();
echo $users->count();
The code triggers a sql statement like select count(*) from users.. instead looping through the $user collection.
Hydrating objects
Not always is necessary to load a collection of entities. If you are creating a blog system, we need to provide only a list of post titles. This infrasrtucture can be inproved by Hydrating objects for read-only purposes.
Useful links
Some links that routes you to official doctrine docs guide.
Improving performance
Doctrine 2, best practices

How to Optimize Models in Zend Framework?

I need to figure out a best practice for utilizing models efficiently in Zend Framework.
Currently, I have classes extending Zend_Db_Table_Abstract which handle my queries to each class' respective table.
When I need to access say 5 of those tables from a controller, I find myself creating 5 new instances of each specific Zend_Db_Table object. This is really ineffective.
I've thought about implementing a Factory pattern to create new instances (or provide existing static copy) but am not sure. Is this the best way to go about it?
What is the correct way to handle models ensuring speed without consuming excessive resources? Should lazy loading come into play here?
[EDIT]
As an example, I have a class I use to handle getting details about a location from a raw search query and need these objects in order to parse the query:
// Initialize database object
$this->dbLocations = new Model_Locations;
$this->dbStates = new Model_States;
$this->dbZipcodes = new Model_Zipcodes;
$this->dbLookup = new Model_Lookup;
In another class, I may need to access those models again so I repeat the above code. Essentially reinitializing objects that could be static/singleton.
I tend to work at the DbTable like you do. I've found it effective when I need to query multiple tables in a single action to create another layer of model above the dbTable. Similar to a service or domain layer. This way I only have to call a single model but I still have the functionality I need.
Here is a simple example that may eventually interact with 5 DbTable classes and most likely a couple of Row classes as well:
<?php
class Application_Model_TrackInfo
{
protected $_track;
protected $_bidLocation;
protected $_weekend;
protected $_shift;
protected $_station;
public function __construct() {
//assign DbTable models to properties for convience
$this->_track = new Application_Model_DbTable_Track();
}
/**
*
* #param type $trackId
* #return type object
*/
public function getByTrackId($trackId) {
$trackData = $this->_track->fetchRow($trackId);
//getAllInfo() Application_Model_Row_TRack
$result = $trackData->getAllInfo();
//returns std object reflecting data from 3 DbTable classes
return $result;
}
/**
*Get Station from trackid through bidlocationid
*
* #param type $trackId
* #return type object
*/
public function getStation($trackId){
$data = $this->_track->fetchRow($trackId);
//This a Application_Model_Row_Track method
$result= $data->getStationFromBidLocation();
return $result;
}
}
I hope this helps.
[EDIT]
Since I wrote this answer I have learned the benefits of Domain Models and Data Mappers. Wow what a difference in my app. Not a magic bullet, but a huge improvement.
Thanks to
Alejandro Gervasio over at PHPMaster.com
Rob Allen at Akrabat.com
and
Pádraic Brady at Surviving The Deepend
for all their help in understanding this pattern.
You seem to be in a possition where you require efficient data management with features that the current Zend framework does not come with. Zend does not have a built in engine for working with databases of any sort, it simply has a wrapper classes which help you write your queries.
What you need is an object relational model (ORM) which is a must-have in a professional framework. As I understand it, ORM is a framework by itself, it has patterns and strongly defined ways of "doing things", supports lazy loading (it takes the most of it) and optimizes your queries to the fullest. When you use ORM you don't even write SQL, instead you need to change your interpretation of data storage, you need to forget about tables and focus on Objects. In Doctrine for example each type (table) is specified by a Class and each record (row) as a class instance where you have access to different methods and properties. It supports event listeners and crazy cascading rellations.
No more need to extract rows from related tables when you delete records (it is automatic), no more need to write complex and chaotic scripts to ensure filesystem synchronisation, you can migrate to almost any db engine at any time (mysql, postgresql, simplesql..) and more..
I've been using Doctrine 2 in conjunction with Symfony 2 framework and I have to say I wouldn't go back to Zend for anything. Yes, it is complex and heavy, but really the ultimate solution. When you come to a moment when you need to manage hundreds of tables with millions of records total - then you will see the difference.
So, final summation:
ORM is what you need, there are many solutions, I know of two really good: Doctrine 1 or 2 and Propel.
P.S.: ORM is an independant part of your system, so you don't really need to use a specific framework, Zend can be configured to work with Doctrine wonderfully :)

DDD and MVC: Difference between 'Model' and 'Entity'

I'm seriously confused about the concept of the 'Model' in MVC. Most frameworks that exist today put the Model between the Controller and the database, and the Model almost acts like a database abstraction layer. The concept of 'Fat Model Skinny Controller' is lost as the Controller starts doing more and more logic.
In DDD, there is also the concept of a Domain Entity, which has a unique identity to it. As I understand it, a user is a good example of an Entity (unique userid, for instance). The Entity has a life-cycle -- it's values can change throughout the course of the action -- and then it's saved or discarded.
The Entity I describe above is what I thought Model was supposed to be in MVC? How off-base am I?
To clutter things more, you throw in other patterns, such as the Repository pattern (maybe putting a Service in there). It's pretty clear how the Repository would interact with an Entity -- how does it with a Model?
Controllers can have multiple Models, which makes it seem like a Model is less a "database table" than it is a unique Entity.
UPDATE: In this post the Model is described as something with knowledge, and it can be singular or a collection of objects. So it's sound more like an Entity and a Model are more or less the same. The Model is an all encompassing term, where an Entity is more specific. A Value Object would be a Model as well. At least in terms of MVC. Maybe???
So, in very rough terms, which is better?
No "Model" really ...
class MyController {
public function index() {
$repo = new PostRepository();
$posts = $repo->findAllByDateRange('within 30 days');
foreach($posts as $post) {
echo $post->Author;
}
}
}
Or this, which has a Model as the DAO?
class MyController {
public function index() {
$model = new PostModel();
// maybe this returns a PostRepository?
$posts = $model->findAllByDateRange('within 30 days');
while($posts->getNext()) {
echo $posts->Post->Author;
}
}
}
Both those examples didn't even do what I was describing above. I'm clearly lost. Any input?
Entity
Entity means an object that is a single item that the business logic works with, more specifically those which have an identity of some sort.
Thus, many people refer to ORM-mapped objects as entities.
Some refer to as "entity" to a class an instance of which represents a single row in a database.
Some other people prefer to call only those of these classes as "entity" which also contain business rules, validation, and general behaviour, and they call the others as "data transfer objects".
Model
A Model is something that is not directly related to the UI (=View) and control flow (=Controller) of an application, but rather about the way how data access and the main data abstraction of the application works.
Basically, anything can be a model that fits the above.
MVC
You can use entities as your models in MVC. They mean two different things, but the same classes can be called both.
Examples
A Customer class is very much an entity (usually), and you also use it as part of data access in your app. It is both an entity and a model in this case.
A Repository class may be part of the Model, but it is clearly not an entity.
If there is a class that you use in the middle of your business logic layer but don't expose to the rest of the application, it may be an entity, but it is clearly not a Model from the perspective of the MVC app.
Your example
As for your code examples, I would prefer the first one.
A Model is a class that is used as a means of data abstaction of an application, not a class which has a name suffixed with "Model". Many people consider the latter bloatware.
You can pretty much consider your Repository class as part of your model, even if its name isn't suffixed with "Model".
I would add to that the fact that it is also easier to work with the first one, and for other people who later may have to understand your code, it is easier to understand.
All answers are a heavy mashup of different things and simply wrong.
A model in DDD is much like a model in the real world:
A simplification and abstraction of something.
No less and no more.
It has nothing to do with data nor objects or anything else.
It's simply the concept of a domain part. And in also every complex domain
there is always more than one model, e.g. Trading, Invoicing, Logistics.
An entity is not a "model with identity" but simply an object with identity.
A repository is not just a 1st level cache but a part of the domain too.
It is giving an illusion of in-memory objects and responsible for fetching
Aggregates (not entities!) from anywhere and saving them
i.e. maintaining the life cycle of objects.
The "model" in your application is the bit which holds your data. The "entity" in domain-driven design is, if I remember correctly, a model with an identity. That is to say, an entity is a model which usually corresponds directly to a "physical" element in a database or file. I believe DDD defines two types of models, one being the entity, the other being the value, which is just a model without and identity.
The Repository pattern is just a type of indexed collection of models/entities. So for instance if your code wants order #13, it will first ask the repository for it, and if it can't get it from there, it will go and fetch it from wherever. It's basically a level 1 cache if you will. There is no difference in how it acts with a model, and how it acts with an entity, but since the idea of a repository is to be able to fetch models using their IDs, in terms of DDD, only entities would be allowed into the repository.
A simple solution using service and collection:
<?php
class MyController {
public function index() {
$postService = ServiceContainer::get('Post');
$postCollection = $postService->findAllByDateRange('within 30 days');
while($postCollection->getNext()) {
echo $postCollection->current()->getAuthor();
}
}
}
EDIT:
The model(class) is the simple representation of the entity scheme. The model(object) is a single entity. The service operates on models and provides concrete data to the controllers. No controller has any model. The models stand alone.
On the other "side", mappers map the models into persistance layers (e.g: databases, 3rd party backends, etc).
while this is specifically about Ruby on Rails, the same principles and information still apply since the discussion is around MVC and DDD.
http://blog.scottbellware.com/2010/06/no-domain-driven-design-in-rails.html

Categories