31 января 2025 г.

Laravel - Полиморфная связь

 

$table->morphs('noteable'); — это метод в Laravel, который создает два столбца в таблице базы данных для реализации полиморфной связи (polymorphic relationship). Полиморфная связь позволяет одной модели быть связанной с несколькими другими моделями через единый интерфейс.

Что делает morphs?

 

Метод morphs создает два столбца в таблице:

  1. noteable_id — целочисленный столбец, который хранит ID связанной модели.

  2. noteable_type — строковый столбец, который хранит имя класса связанной модели.

Эти два столбца позволяют одной модели (например, Note) быть связанной с разными моделями (например, Contact, Task, Event) без необходимости создания отдельных внешних ключей для каждой связи.

Пример использования

В вашем случае, сущность Note может быть связана с разными моделями (Contact, Task, Event). Вместо того чтобы создавать отдельные столбцы в таблице notes для каждой связи (например, contact_id, task_id, event_id), вы используете полиморфную связь.

Миграция для notes:

php
Copy
Schema::create('notes', function (Blueprint $table) {
    $table->id();
    $table->text('content');
    $table->morphs('noteable'); // Создает noteable_id и noteable_type
    $table->timestamps();
});

После выполнения миграции в таблице notes появятся столбцы:

  • noteable_id (тип bigInteger) — ID связанной модели.

  • noteable_type (тип string) — имя класса связанной модели (например, App\Models\Contact, App\Models\Task).

Модель Note:

В модели Note вы определяете полиморфную связь с помощью метода morphTo:

php
Copy
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Note extends Model
{
    protected $fillable = ['content', 'noteable_id', 'noteable_type'];

    public function noteable(): MorphTo
    {
        return $this->morphTo();
    }
}

Модели, которые могут иметь заметки:

В моделях, которые могут иметь заметки (например, Contact, Task, Event), вы определяете обратную связь с помощью метода morphMany:

php
Copy
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Contact extends Model
{
    public function notes(): MorphMany
    {
        return $this->morphMany(Note::class, 'noteable');
    }
}

class Task extends Model
{
    public function notes(): MorphMany
    {
        return $this->morphMany(Note::class, 'noteable');
    }
}

class Event extends Model
{
    public function notes(): MorphMany
    {
        return $this->morphMany(Note::class, 'noteable');
    }
}

Как это работает на практике?

  1. Создание заметки для контакта:

    php
    Copy
    $contact = Contact::find(1);
    $note = new Note(['content' => 'Это заметка для контакта.']);
    $contact->notes()->save($note);

    В таблице notes будет запись:

    • noteable_id = 1 (ID контакта)

    • noteable_type = App\Models\Contact

  2. Создание заметки для задачи:

    php
    Copy
    $task = Task::find(1);
    $note = new Note(['content' => 'Это заметка для задачи.']);
    $task->notes()->save($note);

    В таблице notes будет запись:

    • noteable_id = 1 (ID задачи)

    • noteable_type = App\Models\Task

  3. Получение заметок для контакта:

    php
    Copy
    $contact = Contact::find(1);
    $notes = $contact->notes; // Все заметки, связанные с этим контактом
  4. Получение родительской модели для заметки:

    php
    Copy
    $note = Note::find(1);
    $noteable = $note->noteable; // Получает связанную модель (Contact, Task или Event)

Преимущества полиморфной связи

  • Гибкость: Одна модель (Note) может быть связана с разными моделями без необходимости создания отдельных столбцов для каждой связи.

  • Упрощение структуры базы данных: Не нужно создавать множество внешних ключей для каждой возможной связи.

  • Удобство: Легко добавлять новые типы связей, не изменяя структуру таблицы.

Когда использовать полиморфные связи?

Полиморфные связи полезны, когда одна модель может быть связана с несколькими другими моделями, и вы хотите избежать дублирования кода и избыточности в базе данных. Например:

  • Комментарии к разным сущностям (посты, статьи, видео).

  • Файлы, прикрепленные к разным моделям.

  • Заметки, связанные с разными сущностями.

Комментариев нет:

Отправить комментарий

Laravel - Компоненты Blade

  <x-app-layout> — Компоненты Blade <x-app-layout> — это Blade-компонент , который появился в Laravel 7 и стал активно исполь...