我的模型中有一个父子关系,其中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();
}
}
型号:
// basic concrete ICommand implementation
abstract class CommandBase : ICommand
{
public event EventHandler CanExecuteChanged;
protected void OnCanExecuteChanged ( ) => CanExecuteChanged?.Invoke ( this, EventArgs.Empty );
public virtual bool CanExecute ( object parameter ) => true;
public abstract void Execute ( object parameter );
}
// Now, a more specialized command.
class GenerateReportCommand : CommandBase
{
// In the GOF version of the Command pattern, you inject the context in the command's constructor
public GenerateRepportCommand ( MainViewModel context )
{
_context = context;
// The viewmodel will tell us when to refresh our CanExecute
context.PropertyChanged += ( sender, e ) => OnCanExecuteChanged ( );
}
private MainViewModel _context;
public override bool CanExecute ( object parameter ) => !string.IsNullOrWhiteSpace ( _context.Item1 )
&& !string.IsNullOrWhiteSpace ( _context.Item2 );
public override void Execute ( object parameter )
{
// someDependency.GenerateReport ( _context.Item1, _context.Item2 );
}
}
// Now for the viewmodel side of things
class MainViewModel : ViewModelBase
{
public MainViewModel ( )
{
// You could inject your "report generating" dependencies through here
GenerateReport = new GenerateReportCommand ( this );
}
public string Item1 { get { return _item1; }
set { _item1 = value; OnPropertyChanged ( ); } }
private string _item1;
public string Item2 { get { return _item2; }
set { _item2 = value; OnPropertyChanged ( ); } }
private string _item2;
public ICommand GenerateReport { get; private set; }
}
注意上一个和下一个方法,目前它们适用于所有部分,但不会考虑父/子关系。
我能以任何方式实现这一目标吗?
答案 0 :(得分:0)
这尚未经过测试,但请尝试:
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)->next()
;
答案 1 :(得分:0)
试试这个:
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();
}