Skip to content

Instantly share code, notes, and snippets.

@CamKem
Last active April 26, 2024 02:05
Show Gist options
  • Save CamKem/d1d3824139e69a0f721f88de395111b4 to your computer and use it in GitHub Desktop.
Save CamKem/d1d3824139e69a0f721f88de395111b4 to your computer and use it in GitHub Desktop.
Laravel Polymorphic Follows System.
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('follows', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->morphs('followable');
$table->unique(['user_id', 'followable_id', 'followable_type']);
$table->timestamps();
});
}
};
<?php
declare(strict_types=1);
// For code organisation, goes on the user model.
namespace App\Concerns;
use App\Models\Follow;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
trait HandleFollows
{
public function followers(): HasMany
{
return $this->hasMany(Follow::class, 'followable_id', 'id')
->where('follows.followable_type', $this->getMorphClass());
}
public function following(): HasMany
{
return $this->hasMany(Follow::class, 'user_id', 'id');
}
public function isFollowing(Model $model): bool
{
if ($this->id === $model->id) {
return false;
}
return $this->following()
->where('follows.followable_type', $model->getMorphClass())
->where('follows.followable_id', $model->id)
->exists();
}
public function isFollowedBy(Model $model): bool
{
return $this->followers()->where('user_id', $model->id)->exists();
}
public function follow(Model $model): ?Model
{
if (! $this->isFollowing($model)) {
return Follow::create([
'user_id' => $this->id,
'followable_id' => $model->id,
'followable_type' => $model->getMorphClass(),
]);
}
return null;
}
public function unFollow(Model $model): int
{
return $this->following()
->where('followable_id', $model->id)
->where('followable_type', $model->getMorphClass())
->delete();
}
}
<?php
declare(strict_types=1);
// Goes on the models we want the user to allow to follow (Posts, Tags, etc...)
namespace App\Traits;
use App\Models\Follow;
use App\Models\User;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait HasFollowers
{
public function followers(): MorphMany
{
return $this->morphMany(Follow::class, 'followable');
}
public function isFollowedBy(User $user): bool
{
return $this->followers()->where('user_id', $user->id)->exists();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment