Last active
June 20, 2023 01:13
-
-
Save stevebauman/d1c2c1d08121f5d2d567c7c556b1e5c3 to your computer and use it in GitHub Desktop.
Laravel model trait for easily adding self-referential tables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
use Illuminate\Database\Eloquent\Builder; | |
trait IsSelfReferencing | |
{ | |
/** | |
* The self referencing key on the database table. | |
* | |
* @var string | |
*/ | |
protected $referenceKey = 'parent_id'; | |
/** | |
* The belongsTo parent relationship. | |
* | |
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo | |
*/ | |
public function parent() | |
{ | |
return $this->belongsTo(static::class, $this->referenceKey); | |
} | |
/** | |
* The hasMany children relationship. | |
* | |
* @return \Illuminate\Database\Eloquent\Relations\HasMany | |
*/ | |
public function children() | |
{ | |
return $this->hasMany(static::class, $this->referenceKey); | |
} | |
/** | |
* The hasMany descendants relationship. | |
* | |
* @return \Illuminate\Database\Eloquent\Relations\HasMany | |
*/ | |
public function descendants() | |
{ | |
return $this->children()->with('descendants'); | |
} | |
/** | |
* Determine if the record has no parent. | |
* | |
* @return bool | |
*/ | |
public function isRoot() | |
{ | |
return is_null($this->{$this->referenceKey}); | |
} | |
/** | |
* Determine if the record is a child of another. | |
* | |
* @return bool | |
*/ | |
public function isChild() | |
{ | |
return !$this->isRoot(); | |
} | |
/** | |
* Scope the query for root entries only. | |
* | |
* @param Builder $query | |
* | |
* @return Builder | |
*/ | |
public function scopeRoots(Builder $query) | |
{ | |
return $query->whereNull($this->referenceKey); | |
} | |
} |
Glad I could help you @q10242! 😄
Is there any way to get the siblings of a model ?
public function siblings()
{
return $this->hasMany(static::class, $this->referenceKey, $this->referenceKey);
}
The above code works when the foreign key value is not NULL, but fails essentially for parent categories.
@pravnkay I think you'll have to return differently if the model you're requesting doesn't have a parent_id
:
public function siblings()
{
return $this->isRoot()
? $this->roots()->whereKeyNot($this->{$this->referenceKey})
: $this->hasMany(static::class, $this->referenceKey, $this->referenceKey);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thank you