Skip to content

Instantly share code, notes, and snippets.

@ahmedash95
Last active June 21, 2023 07:46
Show Gist options
  • Save ahmedash95/2b98638a9053871743d6724d3d2ed89b to your computer and use it in GitHub Desktop.
Save ahmedash95/2b98638a9053871743d6724d3d2ed89b to your computer and use it in GitHub Desktop.
Laravel easy relations

Easy Relations

A simple experiment to define Eloquent relationships in a quick easy way using arrays instead of defining a method for each relation.

The scope of EasyRelations is to be only used with simple cases where you dont need to define complex queries or do additional complex queries on the relation.

an example:

<?php

class Post extends Model
{
    use EasyRelations;

    public array $easyRelations = [
        Comment::class => 'hasMany',
        User::class => 'belongsTo',
    ];
}


$post->comments;
$post->user;
Post::with('comments', 'user')->first();
<?php
namespace App\Utils;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Str;
trait EasyRelations
{
protected function getDefinedRelations()
{
return $this->easyRelations ?? [];
}
public function isRelation($key)
{
return parent::isRelation($key) || $this->getEasyRelation($key);
}
public function getEasyRelation($key)
{
$relations = collect($this->getDefinedRelations())
->mapWithKeys(function ($relation, $class) {
$key = Str::endsWith($relation, 'Many') ? Str::plural(class_basename($class)) : class_basename($class);
return [Str::kebab($key) => ['model' => $class, 'type' => $relation]];
})->toArray();
$key = Str::kebab($key);
if (!array_key_exists($key, $relations)) {
return null;
}
return $relations[$key];
}
public function getRelationValue($key)
{
$definition = $this->getEasyRelation($key);
if (is_null($definition)) {
return parent::getRelationValue($key);
}
$relation = $this->createRelationObject($key, $definition);
return tap($relation->getResults(), function ($results) use ($key) {
$this->setRelation($key, $results);
});
}
public function relationResolver($class, $key)
{
$resolver = parent::relationResolver($class, $key);
if (!is_null($resolver)) {
return $resolver;
}
$definition = $this->getEasyRelation($key);
if (is_null($definition)) {
return null;
}
return fn() => $this->createRelationObject($key, $definition);
}
public function createRelationObject($key, $definition): Relation
{
return match ($definition['type']) {
'belongsTo' => $this->belongsTo($definition['model'], null, null, $key),
'morphMany' => $this->morphMany($definition['model'], Str::singular($key) . 'able'),
'hasMany' => $this->hasMany($definition['model']),
default => null, // TODO: support other relation types
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment