在Laravel中获取集合中的下一个对象

时间:2016-12-16 12:37:49

标签: laravel laravel-collection

我有多个属于Chapter的多个Module

在章节页面上,我想检查一下我是否在模块中的最后一个,但是我有点卡住了。

// inside Chapter model.
// The $module var is a made by something like Module::with('chapters')->find(1);
public function getNext($module){

    // Convert to array so we can call some of
    // the array functions to navigate the array
    $chapters = $module->chapters->keyBy('id')->toArray();

    // get the last element in the array
    end($chapters);

    // If the last element's key is the same as this one,
    // there is no "next" link
    if(key($chapters) == $this->id){
        return false;
    }

    // So there must be a next link. First, reset internal array pointer
    reset($chapters);

    // Advance it to the current item
    while (key($chapters) !== $this->id) next($chapters);

    // Go one further, returning the next item in the array
    next($chapters);

    // current() is now the next chapter 
    return current($chapters);
}

酷!所以这让我知道是否有下一章,甚至将它作为一个包含所有数据的数组返回。但是我遇到了很多问题。 Chapter还有其他一些方法,我可以在下一个方法中调用它们。元素作为一个数组,而不再是一个对象。

// Chapter.php
public function url(){
    return url('chapter/' . $this->id);
}


$module = Module::with('chapters')->find(1);
$chapter = Chapter::find(1);
$next = $chapter->getNext($module);
if( $next )
  echo $next->url();

这给了我(显然)

  

调用数组

上的成员函数url()

所以我需要重写这个函数,但是我不能弄清楚如何在Laravel集合中获取下一个对象。

public function getNext($module){
    $last = $module->chapters->last();

    // If the last element's key is the same as this one,
    // there is no "next" link
    if($last->id == $this->id){
        return false;
    }

    ....

如何遍历集合以将下一章作为对象?

2 个答案:

答案 0 :(得分:0)

稍等一下,我找到了自己的解决方案:

public function getNext($module){
    $last = $module->chapters->last();

    // If the last element's key is the same as this one,
    // there is no "next" link
    if($last->id == $this->id){
        return false;
    }

    $current_order = $this->order;
    $filtered = $module->chapters->filter(function ($item) use ($current_order) {
        return $item->order > $current_order;
    });
    return $filtered->first();
}

打开任何其他更简洁的方式来做到这一点!感谢

答案 1 :(得分:0)

您可以将collection macros创建为:

Collection::macro('previous', function ($key, $value = null) {
    if (func_num_args() == 1) $value = $key; $key = 'id';

    return $this->get($this->searchAfterValues($key, $value) - 1);
});

Collection::macro('next', function ($key, $value = null) {
    if (func_num_args() == 1) $value = $key; $key = 'id';

    return $this->get($this->searchAfterValues($key, $value) + 1);
});

Collection::macro('searchAfterValues', function ($key, $value) {
    return $this->values()->search(function ($item, $k) use ($key, $value) {
                             return data_get($item, $key) == $value;
                        });
});

然后您可以将其用作:

$module = Module::with('chapters')->find(1);
$chapter = Chapter::find(1);

$next = $module->chapters->next($chapter->id)
// or 
$next = $module->chapters->next('id', $chapter->id)