diceline-chartmagnifierquestion-marktwitter-whiteTwitter_Logo_Blue

Today I Learned

How to use Laravel's Tappable trait to achieve fluency

Given the following schemas:

Schema::create('skills', function (Blueprint $table) {
    $table->id();
    $table->string("name");
});
//pivot table
Schema::create('category_skill', function (Blueprint $table) {
    $table->id();
    $table->foreignId("skill_id")->constrained();
    $table->foreignId("category_id")->constrained();
});
//the categories table will be omitted for brevity

Suppose you have to write a method which created a skill, attached multiple categories to it and returned the created skill afterwards:

class CreateSkillAction
{
    public function execute(SkillDTO $skillData): Skill
    {
       ...
    }
}

You could easily achieve this with the following code:

public function execute(SkillDTO $skillData): Skill
{
    $skill = Skill::create($skillData->attributes());
    $skill->categories()->attach($skillData>categories);
    return $skill;
}

But if you wanted to make it a bit more fluent - akin to using fluent interfaces - you could do the following:

1. Add the Tappable trait to you model:

class Skill extends Model
{
    use \Illuminate\Support\Traits\Tappable;
    ...
}

2. Rewrite the execute method to use the tap method - now present on the model:

public function execute(SkillDTO $skillData): Skill
{
    return Skill::create($skillData->attributes())
        ->tap(fn($skill)=>$skill->categories()->attach($skillData->categories));
}