Silverstripe Version: 4.1
Question:
I’m trying to get a bunch of DB records into an array and then shuffle them.
I’ve truncated this code to just be one set of 3 questions, in reality I need to get 4 sets of random questions from different categories.
$allQuestions = Question::get();
$random = DB::get_conn()->random();
$questions = $allQuestions
->filter(['CategoryID' => 1, 'TypesID' => 1])
->sort($random)
->limit(3);
foreach ($questions as $question)
{
echo 'Question: '.$question->ID.'<br/>';
}
$questions->sort("rand()");
echo 'After shuffle <br/>';
foreach ($questions as $question)
{
echo 'Question: '.$question->ID.'<br/>';
}
Out put
Question: 5
Question: 2
Question: 4
After shuffle
Question: 5
Question: 2
Question: 3
Why has 4 changed to 3? I’m expecting to see the same 5,2,4 in a different order. I assume this is to do with SS ORM “lazy loading” but it was already looped in the first loop.
Do I have to use arraylist and all the non native stuff or?
As far as I know, the sort()
method won’t do what you’re expecting (ie. shuffle the instance of the datalist you already have). Instead, it will return a new datalist.
So you probably need to do:
$sortedQuestions = $questions->sort("rand()");
foreach ($sortedQuestions as .....
As an aside, rather than specifying the rand()
method, you’re safer using the following (it stops your code being MySQL-specific):
$random = DB::get_conn()->random();
$sortedQuestions = $questions->sort($random);
https://docs.silverstripe.org/en/4/developer_guides/model/data_model_and_orm/#sorting
Thanks for replying, I do appreciate it!
I’ve read the docs - that’s how I got as far as I did…
I’ve used your rand change with no effect:
$allQuestions = Question::get();
$random = DB::get_conn()->random();
$questions = $allQuestions
->filter(['CategoryID' => 1, 'TypesID' => 1])
->sort($random)
->limit(3);
foreach ($questions as $question)
{
echo 'Question: '.$question->ID.'<br/>';
}
$random = DB::get_conn()->random();
$sortedQuestions = $questions->sort($random);
echo 'After shuffle <br/>';
foreach ($sortedQuestions as $question)
{
echo 'Question: '.$question->ID.'<br/>';
}
Out put:
Question: 4
Question: 1
Question: 2
After shuffle
Question: 1
Question: 2
Question: 3
In other words, no change
The results would suggest that it’s re-running the query. You could possibly confirm this by adding ?showqueries=inline
to the URL (you need to be in dev mode)
@Tim Yeah, it is re-running the query again.
Even this reruns the query:
$questions = $allQuestions
->filter(['CategoryID' => 1, 'TypesID' => 1])
->sort("rand()")
->limit(3);
foreach ($questions as $question) echo 'Question: '.$question->ID.'<br/>';
$questions->sort("rand()");
echo 'After shuffle <br/>';
foreach ($questions as $question) echo 'Question: '.$question->ID.'<br/>';
Results in:
Question: 2
Question: 3
Question: 4
After shuffle
Question: 5
Question: 2
Question: 1