如何从具有父子关系的模型中获取下一个和上一个记录

Posted

技术标签:

【中文标题】如何从具有父子关系的模型中获取下一个和上一个记录【英文标题】:How to get next and previous records from a model with a parent child relationship 【发布时间】:2018-03-23 14:12:24 【问题描述】:

我的模型中有父子关系,Section 可以有很多子部分。所以在我的模型中,我将表格加入到自身中,并使用parent 列我可以确定哪个部分是父/子。

我的问题是如何检索小节的下一个和上一个记录?

我的Section 模特:

    class Section extends Model
    
        use BelongsToSortedManyTrait, SortableTrait;


        public $fillable = [
            'id',
            'name',
            'description',
            'parent',
            'position'
        ];


        public function subsections() 
            return $this->hasMany(self::class, 'parent')->sorted();
        

       public function next()
        // get next record
        return self::where('id', '>', $this->id)->orderBy('id','asc')->first();

       

       public  function previous()
        // get previous record
        return self::where('id', '<', $this->id)->orderBy('id','desc')->first();

    

    

注意上一个和下一个方法,目前它们适用于所有部分,但不会考虑父/子关系。

我有什么办法可以做到这一点?

【问题讨论】:

self:: 更改为$this-&gt; 可能会修复[未测试] 在一个小节上调用next() 应该会得到下一个小节,对吧?不是下一个父部分。 @JonasStaudenmeir 它将获得下一个节记录,这可能是使用同一张表的父节。 当你在孩子(小节)时,你想访问父母的下一个/上一个兄弟姐妹,对吧? 【参考方案1】:

这还没有经过测试,但可以尝试:

self::where('parent', $this->parent)
    ->where('id', '<', $this->id)
    ->orderBy('id','desc')
    ->first();

将父级添加到查询中会将下一个值限制为具有相同父级 ID 的值。然后你可以这样使用:

$subsection = Section::find(2);
$next = $subsection->next();
$prev = $subsection->previous();

此外,最好将下一个和上一个父查询设为可选:

public function next($parent = false) 
    $query = self::query();

    if ($parent) 
        $query = $query->where('parent', $this->parent);
    

    $query = $query->where('id', '<', $this->id)
    ->orderBy('id','desc')
    ->first();

这将允许您检查下一节和上一节以及小节。

一切顺利。

更新(API 解决方案 - 尚未测试)

$section = Section::find($id); // Whatever the section id is;

$subsection = Section::where('parent', $section->id)->first();

return [
    'section'         => $section,
    'next_section'    => $section->next()->id,
    'prev_section'    => $section->prev()->id,
    'subsection'      => $subsection,
    'next_subsection' => $subsection->next(true)->id,
    'prev_subsection' => $subsection->prev(true)->id,
];

在下一节调用时,您可以传递子节 id 并在返回 api 之前运行 next/prev:

$subsection = Section::find(1)-&gt;next();

【讨论】:

那么,如果我的 API 中有一个查询构建器,它返回带有子部分的部分的 JSON 响应,我如何使用上述函数来包含下一个和上一个记录? public function first() return $this-&gt;model-&gt;with('sections.subsections')-&gt;first(); 您可以使用新函数映射返回的集合以添加下一个和上一个。或者,您可以创建一个返回所需内容的新数组。但是,prev 和 next 函数是基于有一个小节开始的。我会更新我的答案。 @user3574492 您是要检索 api 中的所有小节,还是只检索一个然后指向下一个和上一个(如果存在)? 所有部分以及小节。如果存在,我希望最终的 JSON 包含部分和小节的下一个和上一个记录。希望这是有道理的。 我知道如果您已经有一个小节记录开始,您的答案将完美无缺,但由于我使用 JSON API 的查询构建器,它的工作方式略有不同,因为我不能使用 Eager加载等...【参考方案2】:

试试这个:

public function next()
    $id = $this->parent ?: $this->id;
    return self::where('id', '>', $id)->orderBy('id','asc')->first();


public  function previous()
    $id = $this->parent ?: $this->id;
    return self::where('id', '<', $id)->orderBy('id','desc')->first();

【讨论】:

以上是关于如何从具有父子关系的模型中获取下一个和上一个记录的主要内容,如果未能解决你的问题,请参考以下文章

从同一表中获取具有级别的父子关系

PHP MYSQL 下一个和上一行

Laravel从模型中获取具有特定数据和关系的记录

如何从单个 MySQL 查询中获取 Parent 的所有子记录 [重复]

Laravel 雄辩模型如何从关系表中获取数据

如何在维度模式中建模父子关系表