0
\$\begingroup\$

I've got an object $contest which is a Symfony entity that has some other entities assigned. I can get them by $content->getEntries();. That will return an object with the lazyloaded db objects. I need to display them in a random order.

$tempEntries = $contest->getEntries();
$entries = array();
if (count($tempEntries)) {
    foreach ($tempEntries as $temp) {
        $entries[] = $temp;
    }
    shuffle($entries);
}

This is the code I use currently. I loop through all elements (if there are any) and then shuffle them. I feel like the looping through them is a wast of resources.

Any advice on how to improve this?

\$\endgroup\$
  • 1
    \$\begingroup\$ What's the return value of getEntries? If it's an ArrayCollection, you could simply use $entries = $contest->getEntries()->toArray(); and simply shuffle($entries); without the loop \$\endgroup\$ – Elias Van Ootegem Mar 27 '15 at 9:14
2
\$\begingroup\$

You can use native shuffling (if you don't use KnpPaginator):

$entries = $contest->getEntries()->toArray();
shuffle($entries);

Also if you need all entities you can write:

$entriesCollection = $contest->getEntries();
if ($entriesCollection instanceof PersistentCollection) {
    $entriesCollection->initialize();
}
$entries = $entriesCollection->toArray();
shuffle($entries);

Alternatively you can dig to @ORM\OrderBy and custom DQL functions to use SQL ORDER BY RAND(). Also this approach would work better with KnpPaginator

In response to comment:

Doctrine mostly uses proxies on your classes instead of directly use them, because of lazy loading and optimization purposes, also doctrine has abstraction over basic arrays implementing own Collection interface that has some useful methods like map, exist and so on. PersistentCollection is proxy (lazy) collection implementing Collection interface it can be returned if you just requested some object from repository and trying to use some field that uses an array of objects so in some cases (like that) it's better to force loading of objects via initialize method (don't worry it won't load them twice). Also all objects requested from repository are not your classes they are just proxies extending your entities and implementing Proxy interface so be careful! If something gone wrong in your database layer try to add the following:

if ($yourEntityLoadedFromSomeWhere instanceof Proxy) {
    $yourEntityLoadedFromSomeWhere->__load();
}
\$\endgroup\$
  • \$\begingroup\$ Nice @smt. Could you please explain me when there is a PersistentCollection and when not and what the initialize does to it. Thanks. \$\endgroup\$ – wawa May 21 '15 at 12:09
  • \$\begingroup\$ @wawa Updated answer \$\endgroup\$ – smt May 24 '15 at 20:01
2
\$\begingroup\$
  • You don't need a temporary variable $tempEntries
  • You don't need to check if the array is empty, if the array is empty shuffle will just do nothing

The code you need may look like:

$entries = $contest->getEntries();
shuffle($entries);
\$\endgroup\$
  • \$\begingroup\$ Please add some context to your answer. \$\endgroup\$ – Kid Diamond May 4 '15 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.