Buy Access to Course
08.

Tricks with ArrayCollection

Share this awesome video!

|

Keep on Learning!

Oh man, the project manager just came to me with a new challenge. Showing all the notes below is great, but they want a new section on top to easily see how many notes have been posted during the past 3 months.

Hmm. In showAction(), we need to somehow count all the recent notes for this Genus. We could start with $recentNotes = $genus->getNotes()... but that's everything. Do we need to finally stop being lazy and make a custom query? Not necessarily.

Remember: getNotes() returns an ArrayCollection object and it has some tricks on it - like a method for filtering! Chain a call to the filter() method and pass this an anonymous function with a GenusNote argument. The ArrayCollection will call this function for each item. If we return true, it stays. If we return false, it disappears.

Easy enough! Return $note->getCreatedAt() > new \DateTime('-3 months');:

// ... lines 1 - 12
class GenusController extends Controller
{
// ... lines 15 - 57
public function showAction($genusName)
{
// ... lines 60 - 85
$recentNotes = $genus->getNotes()
->filter(function(GenusNote $note) {
return $note->getCreatedAt() > new \DateTime('-3 months');
});
// ... lines 90 - 94
}
// ... lines 96 - 120
}

Next, pass a new recentNoteCount variable into twig that's set to count($recentNotes):

// ... lines 1 - 12
class GenusController extends Controller
{
// ... lines 15 - 57
public function showAction($genusName)
{
// ... lines 60 - 90
return $this->render('genus/show.html.twig', array(
'genus' => $genus,
'recentNoteCount' => count($recentNotes)
));
}
// ... lines 96 - 120
}

In the template, add a new dt for Recent Notes and a dd with {{ recentNoteCount }}:

42 lines | app/Resources/views/genus/show.html.twig
// ... lines 1 - 4
{% block body %}
<h2 class="genus-name">{{ genus.name }}</h2>
<div class="sea-creature-container">
<div class="genus-photo"></div>
<div class="genus-details">
<dl class="genus-details-list">
// ... lines 12 - 17
<dt>Recent Notes</dt>
<dd>{{ recentNoteCount }}</dd>
</dl>
</div>
</div>
<div id="js-notes-wrapper"></div>
{% endblock %}
// ... lines 25 - 42

All right - give it a try! Refresh. Six notes - perfect: we clearly have a lot more than six in total.

The ArrayCollection has lots of fun methods on it like this, including contains(), containsKey(), forAll(), map() and other goodies.

Don't Abuse ArrayCollection

Do you see any downsides to this? There's one big one: this queries for all of the notes, even though we don't need them all. If you know you'll only ever have a few notes, no big deal. But if you may have many notes: don't do this - you will feel the performance impact of loading up hundreds of extra objects.

So what's the right way? Finally making a custom query that only returns the GenusNote objects we need. Let's do that next.