Skip to content

Instantly share code, notes, and snippets.

@stevebauman
Last active June 20, 2023 01:13
Show Gist options
  • Save stevebauman/d1c2c1d08121f5d2d567c7c556b1e5c3 to your computer and use it in GitHub Desktop.
Save stevebauman/d1c2c1d08121f5d2d567c7c556b1e5c3 to your computer and use it in GitHub Desktop.
Laravel model trait for easily adding self-referential tables
<?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);
}
}
@stevebauman
Copy link
Author

Glad I could help you @q10242! 😄

@pravnkay
Copy link

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.

@stevebauman
Copy link
Author

stevebauman commented Apr 10, 2023

@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