【问题标题】:PHP Iterator Custom Sort Order (Laravel 4)PHP迭代器自定义排序顺序(Laravel 4)
【发布时间】:2013-08-28 22:25:57
【问题描述】:

我有一个“Post”对象,通过 IOC 容器访问。各种错误告诉我这个对象的类型最终是“Collection”,它实现了几个接口,包括 IteratorAggregate 和 ArrayAccess。

我想按照特定的顺序显示一组用户自定义的帖子,例如:

$desired=array("69","63","70");//these represent post id's

以这种方式对数组进行排序似乎很复杂,但我想对我的集合进行排序。我一直在研究 usort()、uksort()、Eloquent 的 sortBy()、array_multisort() 的各种组合......但最明显的解决方案会产生像 3、2、1 或 1、2、3 之类的顺序,而不是 2, 1,3。

我最接近这个目标的是获取我想要的,

//BlogController
private function myposts($desired){
    $posts=$this->post->whereIn('id',$desired)->get();
    ...

将 Collection 对象“转换”为数组,

$posts=$posts->toArray();

并使用自定义函数处理数组: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);

然后我可以按正确的顺序对数组进行 vardump,但由于它现在是一个数组,我无法访问我视图中的 $posts 对象。我可以将数组转换回 post 对象吗?

无论如何,这整个方法都感觉很浪费,转换为数组并返回......是吗?有没有更直接的方式对“集合”的内容进行排序?

这个稍微好一点,也许(一个原生的php函数):

array_multisort($desired,$posts,SORT_STRING);
//only works with string keys
//$desire=(1,2,3) will not work!

同样,这适用于数组,但直接在“posts”对象上尝试失败...

最后,我发现使用 Presenter: https://github.com/robclancy/presenter#array-usage 在控制器中完成上述一项操作后,它可以在视图中工作:

@foreach($posts as $post)
<?php $post=new PostPresenter($post) ?>
{{View::make('site.post.article')->with(compact('post'))}}
@endforeach

这终于奏效了,但感觉还是有很长的路要走。有没有更好的方法来完成这项任务?一种方法与另一种方法的性能问题或最佳实践?提前感谢任何能够提供帮助的人。

【问题讨论】:

    标签: php arrays sorting laravel laravel-4


    【解决方案1】:

    您可以使用 Collections 自己的 sort 方法并传入回调。回调比较集合中的每两个值,告诉排序方法哪个“更高”。然后 sort 方法对它们进行相应的排序。如果您想要一个特定的值顺序,您只需创建映射并按此排序。更多信息请查看uasort

    $posts->sort(function($a, $b){
        $desired=array("69" => 0,"63" => 1,"70" =>2);
        if(!array_key_exists($a,$desired) || !array_key_exists($b,$desired) || $a == $b){
            return 0
        }
        else{
            return ($desired[$a] < $desired[$b]) ? -1 : 1;
        }
    });
    

    【讨论】:

    • 我要试试这个方法,但我应该从闭包外面用 use() 拉入我的“自定义订单”。
    【解决方案2】:

    除了@tim 的回答,您可以将排序后的数组重新分配给新的 Collection 对象:

    $postsArray = $this->posts->toArray();
    
    // Do some sorting/processing, then:
    
    $newCollection = new \Illuminate\Database\Eloquent\Collection( $postsArray );
    

    【讨论】:

    • 当我尝试这个然后尝试遍历 $postsArray 并引用 $post->name 或集合项的任何属性时,我得到错误:'尝试获取非对象的属性'跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多