I have a "Post" object, accessed via the IOC container. Various errors tell me this object's type ends up as a "Collection", which implements several interfaces, including IteratorAggregate and ArrayAccess.
I want to display a user-defined group of posts according to a specific order, e.g.:
$desired=array("69","63","70");//these represent post id's
Just sorting an array in this manner seems complex, but I want to sort my collection. I have been researching various combinations of usort(), uksort(), Eloquent's sortBy(), array_multisort()... but the most obvious solutions result in orders like 3,2,1 or 1,2,3, not 2,1,3.
The closest I have gotten to this goal is to fetch the ones I want,
//BlogController
private function myposts($desired){
$posts=$this->post->whereIn('id',$desired)->get();
...
"convert" the Collection object to an array,
$posts=$posts->toArray();
and treat the array with a custom function: source
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
$sorted=sortArrayByArray($array1,$desired);
I can then vardump the array in the correct order, but since it is now an array, I can't access the $posts object in my view. Can I convert the array back into a post object?
This whole approach feels wasteful anyway, converting to an array and back... is it? Is there a more straightforward way of sorting the contents of a "Collection"?
This is a little better, perhaps (a native php function):
array_multisort($desired,$posts,SORT_STRING);
//only works with string keys
//$desire=(1,2,3) will not work!
Again, this works for arrays, but attempting directly on the "posts" object fails...
Finally, I discovered using a Presenter: https://github.com/robclancy/presenter#array-usage which works in the view, after one of the above is completed in the controller:
@foreach($posts as $post)
<?php $post=new PostPresenter($post) ?>
{{View::make('site.post.article')->with(compact('post'))}}
@endforeach
This finally works, but it still feels like a long way to do it. Is there a better way to accomplish this task? Performance concerns or best practices with one method vs. another? Thanks in advance for anyone able to help.