I'm currently encountering some problems with Doctrine Hydration. I'm using ZF2 to build an API and therefore i need to build some queries that make use of joins.
For now they look somewhat like this:
$qb->select(array('r, a'))
->from('Release\Entity\Release', 'r')
->leftJoin(
'Artist\Entity\Artist', a',
\Doctrine\ORM\Query\Expr\Join::WITH, 'a.id = r.artist'
)
->orderBy('r.id', 'ASC');
So if i hydrate the Result with AbstractQuery::HYDRATE_ARRAY
the result will be an extra array entry for each joined table/entity.
Array
(
[0] => Array
(
[id] => 1
[artist] => 1
[title] => A super nice Release
[digital_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[1] => Array
(
[id] => 1
[first_name] => John
[last_name] => Doe
[artist_name] => JD and the Beat-Machines
[created_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[updated_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[2] => Array
(
[id] => 2
[artist] => 14
[title] => Some other nice album
[digital_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[...]
)
As you can see the artist of the corresponding release [0] is stored into array-key [1].
If I finally print the result as new JsonModel($result)
this doesn't seem a workable way to me.
What i want to achieve is some result like this
Array
(
[0] => Array
(
[id] => 1
[artist] => Array
(
[id] => 1
[first_name] => John
[last_name] => Doe
[artist_name] => JD and the Beat-Machines
[created_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[updated_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[title] => A super nice Release
[digital_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[2] => Array
(
[id] => 2
[artist] => Array
(
[id] => 14
[...]
)
[title] => Some other nice album
[digital_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[...]
)
Maybe someone has a helpful advice how to get such an output :)
I've already tried to use AbstractQuery::HYDRATE_SCALAR
, which comes a bit closer to what i want, but the result of the joined table is not a sub-array of the joined column.
Thanks in advance for every helpful hint :)
regards
Your problem is your mapping it's not good i think you have not a relation between Release and Artist.
You have to set a relation OneToMany between Artist and Release. Like this :
On artist side
/**
* @ORM\OneToMany(targetEntity="Release\Entity\Release", mappedBy="artist")
*/
protected $release;
And Release side
/**
* @ORM\ManyToOne(targetEntity="Artist\Entity\Artist", inversedBy="release")
* @ORM\JoinColumn(name="artist", referencedColumnName="idArtist", onDelete="RESTRICT")
*/
protected $artist;
Don't forget to the Artist side to instanciate a collection like this :
public function __construct()
{
$this->release= new ArrayCollection();
}
with this use :
use Doctrine\Common\Collections\ArrayCollection;
With this you can set your release entity and set the artist whith an artist object. You'll have the result you want.
$release = new Release;
$artist = new Artist;
$release->setArtist($artist);
EDIT When you have your data, you have to populate your entity with it.
If you have a Form, you have to use DoctrineHydrator to achieve this, your object will be correctly hydrated, from your form. This may need to dig into doctrine documentation ;) If your data comes from anywhere else, you can populate your entity with your entity's setters.
For e.g :
$relaseEntity->setDate($data['date']); // Be carefull to Datetime object for this
$releaseEntity->setName($data['name']);
And goes on...