Laravel: разница между использованием трейта и расширением модели

Мы работаем над приложением Laravel с модулем планирования. Модуль имеет три типа классов, которые можно поместить в повестку дня: Задача, Событие и Отдел. Поэтому мы получили следующую диаграмму классов: Диаграмма классов Теперь наш вопрос: если бы мы реализовали эту диаграмму, должны ли мы использовать черту или расширять планируемую модель.

Планируемая модель:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Plannable extends Model
{
    // Code
}

Модель задачи:

<?php

namespace App;

use App\Plannable;

class Task extends Plannable
{
    // Code
}

Или мы должны использовать это как черту:

Планируемая черта:

<?php

namespace App\Traits;

trait Plannable
{
    // Code
}

Модель задачи:

<?php

namespace App;

use App\Plannable;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use Plannable;
    // Code
}

person Lex de Willigen    schedule 21.05.2019    source источник
comment
Рассматривали ли вы использование полиморфных отношений laravel? Я не уверен, чего вы пытаетесь достичь с помощью черты. laravel.com/docs/5.8/   -  person FunkyMonk91    schedule 21.05.2019
comment
Я поддерживаю голосование за полиморфные отношения.   -  person ceejayoz    schedule 21.05.2019
comment
Нет, я не пытаюсь завести отношения. Я хотел бы предотвратить дублирование кода во всех трех моделях.   -  person Lex de Willigen    schedule 21.05.2019


Ответы (2)


Расширение родительского/абстрактного класса лучше всего использовать, когда все модели имеют общие характеристики, но ведут себя (функционируют) уникальным образом. Например, Cars и Motorcycles оба являются Vehicles. У них общие характеристики (например, фары, индикаторы, двигатели, трансмиссии и т. д.), но способ их operate() уникален для разных классов.

Трейты, с другой стороны, лучше использовать, когда использующие классы (или модели Eloquent в данном случае) требуют общей функциональности (то есть методов), несмотря на то, что они имеют разные характеристики.

Не зная больше о вашем проекте, кажется, что вы ищете последнюю, поскольку каждая модель имеет общую функциональность (возможно, addToCalendar(), reschedule() и т. д.), несмотря на разные характеристики.

person Erich    schedule 26.07.2019

Когда вы пытаетесь расширить класс, означает, что "является" отношением, "Автомобиль" расширяет "Автомобиль", "Автомобиль" является "Автомобилем". В вашем примере Task "является" Plannable. Это все же?

С другой стороны, трейты используют другой подход, вроде «Автомобиль использует колеса». В вашем примере снова Task использует Plannable. Выглядит лучше, чем расширение, я думаю?

Трудно сказать больше, не понимая, какие функции вы будете чертить для этой реализации. Надеюсь, это дает некоторые идеи.

person Yavuz Koca    schedule 21.05.2019
comment
Хорошее сравнение. Я пытаюсь добиться следующего: я хотел бы сделать некоторый общий код, применимый ко всем моделям, которые можно разместить в календаре. Я бы не хотел писать один и тот же код во всех трех отдельных моделях. - person Lex de Willigen; 21.05.2019