SilverStripe random order for ArrayList()
Asked Answered
A

2

6

I know that we can randomly sort a DataList with the following:

$example = Example::get()->sort('RAND()');

But when I try to randomly sort an ArrayList it doesn't work. I can sort an ArrayList by ID DESC, but not with RAND().

Is there a way to make an ArrayList randomly sort its items?

Example:

public function AllTheKits() {
    $kits = Versioned::get_by_stage('KitsPage', 'Live');
    $kitsArrayList = ArrayList::create();

    foreach ($kits as $kit) {
        if ($kit->MemberID == Member::currentUserID()) {
            $kitsArrayList->push($kit);
        }
    }
    return $kitsArrayList;      
}

In a page:

public function getKitsRandom() {
    return $this->AllTheKits()->sort('RAND()');
}

This does not work in a template with <% loop KitsRandom %>

Allhallowtide answered 29/3, 2017 at 20:31 Comment(0)
T
4

Not really. This is the best workaround I can come up with:

foreach($myArrayList as $item) {
    $item->__Sort = mt_rand();
}

$myArrayList = $myArrayList->sort('__Sort');
Trella answered 29/3, 2017 at 21:9 Comment(2)
It's not like I expected but it's efficient enough to not make duplicated codes. I will try this soon. Thanks!Allhallowtide
I tested this in morning... That works perfectly. ThanksAllhallowtide
B
3

You could randomly sort the DataList before you loop over it, instead of trying to randomly sort the ArrayList:

public function AllTheKits($sort = '') {
    $kits = Versioned::get_by_stage('KitsPage', 'Live', '', $sort);
    $kitsArrayList = ArrayList::create();

    foreach ($kits as $kit) {
        if ($kit->MemberID == Member::currentUserID()) {
            $kitsArrayList->push($kit);
        }
    }
    return $kitsArrayList;      
}

public function getKitsRandom() {
    return $this->AllTheKits('RAND()'));
}

As a side note, you can filter the original DataList to fetch KitsPages that relate to this MemberID in the Versioned::get_by_stage call:

public function AllTheKits($sort = '') {
    $kits = Versioned::get_by_stage(
        'KitsPage',
        'Live',
        'MemberID = ' . Member::currentUserID(),
        $sort
    );
    $kitsArrayList = ArrayList::create($kits);

    return $kitsArrayList;      
}

You could also just do this:

return KitsPage::get()->filter('MemberID', Member::currentUserID())->sort('RAND()');

When you are viewing the live site this will only get the live KitPages.

Benn answered 30/3, 2017 at 0:54 Comment(1)
That last approach with filter is definitely the cleanest and also most efficient approach.Gesture

© 2022 - 2024 — McMap. All rights reserved.