По мере перевода частей проекта с yii на laravel, возникает необходимость в реализации на laravel тех же шаблонов, которые были реализованы на yii. Некоторое время назад я рассказывал о том, как на yii реализовать абстрактный метод для моделей. В этой статье я опишу, как сделать тоже самое в laravel.
Ключевым моментом является функция, которая будет вызываться каждый раз после выборки данных из БД и на основе данных будет определять тип модели. В laravel - это функция newFromBuilder
. Для создания объектов нужного класса в моделях eloquent используется newInstance
. Я считаю, что её стоит оставить неизменной, а для определения подкласса на основе данных создать отдельную функцию генератор. Тогда код будет выглядеть следующим образом:
class Plant extends Model
{
protected $table = 'plants';
/**
* Create a new model instance that is existing.
*
* @param array $attributes
* @param string|null $connection
* @return static
*/
public function newFromBuilder($attributes = [], $connection = null)
{
$model = static::newInstanceGenerator((array)$attributes, true);
$model->setRawAttributes((array) $attributes, true);
$model->setConnection($connection ?: $this->connection);
return $model;
}
/**
* Create a new instance of the given model.
*
* @param array $attributes
* @param bool $exists
* @return static
*/
public static function newInstanceGenerator($attributes = [], $exists = false){
$model = null;
if (isset($attributes['type_id'])) {
switch($attributes['type_id']) {
case(PLANT_TYPE_FRUIT):{
$model = new Fruit([]);
break;
}
case(PLANT_TYPE_VEGETABLE):{
$model = new Vegetable([]);
break;
}
}
}
if (!$model) {
$model = new static([]);
}
$model->exists = $exists;
return $model;
}
}
Данный фрагмент, позволит конкретезировать тип объектов, получамых на основе БД. Новых объектов нужно будет использовать генерацию через функцию newInstanceGenerator
:
$fruit = Plant::newInstanceGenerator(['type_id' => PLANT_TYPE_FRUIT], false);
Если сравнивать yii и laravel, то сложность кода в обоих практически одинакова. Когда я пытался разобраться как реализовать этот код, то обращался за помощью к саппорту и они не смогли мне помочь. На мой взгляд, это говорит о том, что существуют проблемы с пониманием единого механизма работы eloquent. C другой стороны, благодаря большому количеству модулей, плагинов и наличию неплохих комментариев в коде очень многие вещи можно узнать читая исходный код.
Надеюсь, что эта небольшая статья поможет кому-нибудь упростить код своего проекта.