Buy

In some ways, not much just changed. Before, we had a genus_scientist table with genus_id and user_id columns. And... we still have that, just with two new columns:

71 lines src/AppBundle/Entity/GenusScientist.php
... lines 1 - 10
class GenusScientist
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
... lines 19 - 31
/**
* @ORM\Column(type="string")
*/
private $yearsStudied;
... lines 36 - 70
}

But, in our app, a ton just changed. That's my nice way of saying: we just broke everything!

Collection of GenusScientists, not Users

For example, before, genusScientists was a collection of User objects, but now it's a collection of GenusScientist objects:

204 lines src/AppBundle/Entity/Genus.php
... lines 1 - 14
class Genus
{
... lines 17 - 71
/**
* @ORM\OneToMany(targetEntity="GenusScientist", mappedBy="genus", fetch="EXTRA_LAZY")
*/
private $genusScientists;
... lines 76 - 202
}

The same thing is true on User:

243 lines src/AppBundle/Entity/User.php
... lines 1 - 16
class User implements UserInterface
{
... lines 19 - 77
/**
* @ORM\OneToMany(targetEntity="GenusScientist", mappedBy="user")
*/
private $studiedGenuses;
... lines 82 - 241
}

Wherever our code was using the studiedGenuses property - to get the collection or change it - well, that code is done broke.

Let's clean things up! And see some cool stuff along the way.

First, because we just emptied our database, we have no data. Open the fixtures file and temporarily comment-out the genusScientists property:

38 lines src/AppBundle/DataFixtures/ORM/fixtures.yml
AppBundle\Entity\Genus:
genus_{1..10}:
... lines 3 - 8
# genusScientists: '3x @user.aquanaut_*'
... lines 10 - 38

We can't simply set a User object on genusScientists anymore: this now accepts GenusScientist objects. We'll fix that in a second.

But, run the fixtures:

./bin/console doctrine:fixtures:load

While that's working, go find GenusController and newAction(). Let's once again use this method to hack together and save some interesting data.

First, remove the two addGenusScientist lines:

148 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 13
class GenusController extends Controller
{
... lines 16 - 18
public function newAction()
{
... lines 21 - 40
$genus->addGenusScientist($user);
$genus->addGenusScientist($user); // duplicate is ignored!
... lines 43 - 52
}
... lines 54 - 146
}

These don't make any sense anymore!

How can we add a new row to our join table? Just create a new entity: $genusScientist = new GenusScientist(). Then, set $genusScientist->setGenus($genus), $genusScientist->setUser($user) and $genusScientist->setYearsStudied(10). Don't forget to $em->persist() this new entity:

153 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 6
use AppBundle\Entity\GenusScientist;
... lines 8 - 14
class GenusController extends Controller
{
... lines 17 - 19
public function newAction()
{
... lines 22 - 42
$genusScientist = new GenusScientist();
$genusScientist->setGenus($genus);
$genusScientist->setUser($user);
$genusScientist->setYearsStudied(10);
$em->persist($genusScientist);
... lines 48 - 57
}
... lines 59 - 151
}

There's nothing fancy going on anymore: GenusScientist is a normal, boring entity.

Using the new Collections

In your browser, try it: head to /genus/new. Genus created! Click the link to see it! Explosion! That's no surprise: our template code is looping over genusScientists and expecting a User object. Silly template! Let's fix that and the fixtures next.

Leave a comment!