Laravel Relatable

Usage

Add the InteractsWithRelated trait to each model that relates to others. The models it relates to don't need the trait, unless they relate back.

use Foxws\Relatable\Concerns\InteractsWithRelated;

class Tag extends Model
{
    use InteractsWithRelated;
}

Attaching

$action->attachRelated($fastpace);            // score and boost default to 1.0
$action->attachRelated($foo, score: 0.5);
$action->attachRelated($chase, score: 0.4, boost: 2.0, options: ['source' => 'manual']);

Attaching a model that is already related updates that relation — a score or boost left null keeps its current value. It returns the Foxws\Relatable\Models\Relatable row.

Mutual relations

Pass mutual: true to relate the model back to this one as well. The relation back gets the same score and boost, unless you give it its own:

$action->attachRelated($foo, score: 1.0, mutual: true, mutualScore: 0.5);

Detaching

$action->detachRelated($foo);               // only Action → Foo
$action->detachRelated($foo, mutual: true); // and Foo → Action

Syncing

syncRelated() relates exactly the given models: missing relations are created, existing ones updated, and the rest removed. Each item is a model, or an array with a model and an optional score, boost and options:

$action->syncRelated([
    $fastpace,
    ['model' => $foo, 'score' => 0.5],
]);

$action->syncRelated([]); // remove all

A plain model keeps the score of an existing relation. With mutual: true, the relations back are created and removed along with them.

$action->relates;                  // cached attribute, highest weight first
$action->getRelates();             // same, uncached
$action->getRelates(Video::class); // only videos (a class or morph alias)

Related models are eager loaded per type, so this is one query per related model type. To eager load them for many models at once:

Tag::with('relatables.related')->get();

Relations

$action->relatables();     // MorphMany: Action → others
$action->relatablesFrom(); // MorphMany: others → Action

Deleting models

Deleting a model deletes its relations in both directions. Soft-deleted models keep them until they're force-deleted. Disable this with relatable.delete_on_model_delete.