Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
$pages->find("sort=random") doesn't work as expected across pagination #266
Short description of the issue
When "sort=random" is used in a $pages->find() selector and the results are paginated, a new random sort is applied on each results page. This means that an item may appear more that once across the paginated results, and navigating back to or reloading a results page shows different results each time.
The random sorting is applied only once across paginated results.
Optional: Suggestion for a possible fix
A solution is to use RAND(N) in the SQL query instead of RAND(), where N is a seed value.
Not sure if there's a good way to be smart about automatically storing and using a seed across pagination so the user (i.e. PW developer) doesn't need to do anything special.
Or if the existing behaviour for the 'random' keyword should be kept and a new keyword introduced for when a seed should be used, e.g. 'random($seed)' where $seed is an integer supplied by the user. It would be up to the user to supply a seed where needed and keep that across the pagination via GET or session variable. Of course this would be more demanding on the user than an automatic solution.
Related forum thread: https://processwire.com/talk/topic/16313-using-a-seed-when-getting-random-pages/
Using a custom session value generated on login should suffice for basic usecases. But as this is not really random – not each refresh is random – it should probably be a new keyword. Maybe randomSession or so. With something like
Another option of storage would be a second GET parameter for pagination, but this one should be toggleable and not enabled by default.
Re: automatic seed - the challenge is that at the time the initial random-sorted $pages->find() is done it's not known if "limit=x" will be used for just a single results PageArray or as part of paginated results.
I had some thoughts about an approach where a hash is created from the selector components (excluding start and limit) and a random integer also generated for use in RAND(N). Then the integer is stored in a session variable named by the hash. On subsequent find() operations a check is made to see if a session variable exists for that hash and if so the integer is used in RAND(N).
But perhaps overly complicated?
I don't think that tying the existing "sort=random" to a seed is a good way to go here, because the intention with it is that it returns a random set. Previous calls are not meant to influence later calls. After all, someone may be doing multiple similar random calls in the same request. If a seeded sort=random is needed as a new feature, then I think we'd go with the