Polymorphic ilişkiler, aynı tabloyu birden fazla model ile ilişkilendirmek için kullanılan güçlü bir özelliktir. Bu yazıda, bir gönderiye veya başka herhangi bir modele "Beğeni (Like)" ekleyebileceğiniz bir sistem kuracağız.
Bu örnek, Trait kullanımıyla kolaylaştırılmış ve yeniden kullanılabilir bir yapı sunmaktadır. Ayrıca, her adımı detaylı bir şekilde açıklayarak kodu anlamanıza yardımcı olacağız.
Adım 1: Veritabanı Tasarımı
likes tablosunu oluşturacak migration dosyasını yazıyoruz. Bu tablo, beğeni işlemlerini saklayacak ve polymorphic ilişkiyi kullanacaktır.
Migration Dosyasıdatabase/migrations/xxxx_xx_xx_create_likes_table.php:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLikesTable extends Migration
{
public function up(): void
{
Schema::create('likes', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');
// Polymorphic ilişki için sütunlar
$table->nullableMorphs('likeable');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('likes');
}
}
nullableMorphs('likeable')metodu, likeable_type ve likeable_id sütunlarını oluşturur.- Bu sütunlar sayesinde, "Like" tablosu herhangi bir model ile ilişkilendirilebilir (ör. Post, Video, Comment).
Adım 2: Likeable Trait
"Beğeni" sistemini destekleyen tüm modellerde kullanılabilecek bir Trait oluşturuyoruz.
Trait Dosyasıapp/Concerns/Likeable.php:
namespace App\Concerns;
use App\Models\Like;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait Likeable
{
protected static function bootLikeable(): void
{
// Model silindiğinde beğenileri de sil
static::deleting(fn($resource) => $resource->likes->each->delete());
}
// Polymorphic ilişkiyi tanımlar
public function likes(): MorphMany
{
return $this->morphMany(Like::class, 'likeable');
}
// Beğeni ekleme metodu
public function like(): void
{
if ($this->likes()->where('author_id', auth()->id())->doesntExist()) {
$this->likes()->create(['author_id' => auth()->id()]);
}
}
// Beğeniyi kaldırma metodu
public function dislike(): void
{
$this->likes()->where('author_id', auth()->id())->get()->each->delete();
}
// Kullanıcının beğenip beğenmediğini kontrol et
public function isLiked(): bool
{
return $this->likes()->where('author_id', auth()->id())->exists();
}
}
bootLikeable(): Bir model silindiğinde ilişkili tüm beğeniler de otomatik olarak silinir.like(): Beğeni ekler. Kullanıcı zaten beğenmişse tekrar eklemez.dislike(): Beğeniyi kaldırır.isLiked(): Kullanıcının modeli beğenip beğenmediğini kontrol eder.
Adım 3: Modellerde Trait Kullanımı
Bu Trait'i kullanacak modellerimize ekleyelim. Örneğin, bir Post modeline beğeni özelliği ekleyelim.
Post Modeliapp/Models/Post.php:
namespace App\Models;
use App\Concerns\Likeable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory, Likeable;
// Diğer Post model özellikleri
}
Adım 4: Like Modeli
Beğeni ilişkisini temsil eden bir model oluşturalım.
Like Modeliapp/Models/Like.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
use HasFactory;
protected $fillable = ['author_id'];
}
Adım 5: Controller İşlemleri
Post modeline "Beğeni ekle" ve "Beğeni kaldır" işlemleri yapacak bir kontrolör yazalım.
Controllerapp/Http/Controllers/PostLikeController.php:
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostLikeController extends Controller
{
public function store(Post $post)
{
$post->like(); // Beğeni ekle
return back()->with('success', 'Post liked!');
}
public function destroy(Post $post)
{
$post->dislike(); // Beğeni kaldır
return back()->with('success', 'Post unliked!');
}
}
Adım 6: Rotayı Tanımlama
Web Routesroutes/web.php:
use App\Http\Controllers\PostLikeController;
Route::post('posts/{post}/like', [PostLikeController::class, 'store'])->name('posts.like');
Route::delete('posts/{post}/like', [PostLikeController::class, 'destroy'])->name('posts.unlike');
Adım 7: Blade'de Kullanım
Son olarak, beğeni sistemini Blade şablonunda kullanalım.
Blade Şablonuresources/views/posts/show.blade.php:
@if ($post->isLiked())
<form action="{{ route('posts.unlike', $post) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">Unlike</button>
</form>
@else
<form action="{{ route('posts.like', $post) }}" method="POST">
@csrf
<button type="submit">Like</button>
</form>
@endif
<p>{{ $post->likes->count() }} likes</p>
Sonuç
Artık bir gönderiyi beğenebilir, beğeniyi kaldırabilir ve toplam beğeni sayısını gösterebilirsiniz. Bu yapı, başka modellerde de (örneğin, videolar, yorumlar) kolaylıkla kullanılabilir.
