Laravel'de Polymorphic İlişkilerle "Like" Sistemi

L

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 Modeli
app/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 Modeli
app/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.

Controller
app/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 Routes
routes/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 Şablonu
resources/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.

By Aydın Yağız

Aydın Yağız

Teknolojiye olan tutkumla inovasyonu destekler, kullanıcı deneyimini önceliklerim arasına alırım. Kendi yeteneklerimi ve bilgilerimi paylaşarak, daha geniş bir topluluğun faydalanmasını sağlarım. İş birliği içinde hareket ederek, geleceğin teknoloji dünyasına katkıda bulunmayı hedeflerim. Sizi de bu heyecan verici yolculuğa davet ediyor, fikirlerinizi paylaşmaya ve teknolojiye dair sınırları zorlamaya teşvik ediyorum. Birlikte büyüyelim ve yeni ufuklara açılalım!

İletişime Geçin

Kodlama dünyasına adım atın ve deneyimlerinizi paylaşın. Siz de bu aktif topluluğa katılarak yeni bağlantılar kurun, fikir alışverişinde bulunun ve bilgi birikiminizi artırın.

Özelleştir

Farklı yazı tipleri ve renk seçenekleriyle stilinizi kişiselleştirin. Aşağıdaki örneklerden birini deneyerek sizin için en uygun olanı seçin.

Yazı Tipi Örnekleri

Renk Örnekleri