Полиморфные модели Laravel по типам

Источник: «Laravel Polymorphic Models By Type»
Узнайте, как использовать полиморфные модели по типу в Laravel для работы с различными типами параметров в одной таблице базы данных. В статье рассматривается процесс использования полиморфных отношений для работы с различными типами параметров в одной таблице базы данных.

Мне был нужен лучший способ работы с различными типами моделей на основе одной таблицы базы данных.

В качестве примера приведу таблицу настроек для приложения, способную возвращать различные типы настроек в зависимости от типа столбца строки.

Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('type');
$table->text('settings');
$table->timestamps();
});

Столбец type будет использоваться для определения типа настроек, хранящихся в столбце settings. Это может быть что-то вроде email, slack, sms и т. д. Столбец settings представляет собой JSON столбец, хранящий настройки для типа уведомления, такие как адрес электронной или токен и канал для отправки уведомления в slack.

Поскольку значение столбца settings может состоять из различных типов настроек, понадобился способ обработки этого в приложении. Для каждого типа настроек нужно использовать разные классы, например EmailSetting, SlackSetting, SmsSetting и т. д.

EmailSetting будет содержать метод getEmail для получения адреса электронной почты из json-столбца настроек.

<?php

namespace App\Models\Notifications;

use Illuminate\Database\Eloquent\Model;

class EmailSetting extends Model
{
public function getEmail()
{
return $this->settings['email'] ?? '';
}
}

В то время как класс SlackSetting будет содержать метод getChannel для получения канала из json-столбца настроек и getToken для получения API-токена.

<?php

namespace App\Models\Notifications;

use Illuminate\Database\Eloquent\Model;

class SlackSetting extends Model
{
public function getChannel()
{
return $this->settings['channel'] ?? '';
}

public function getToken()
{
return $this->settings['token'] ?? '';
}
}

Полиморфные отношения

Чтобы справиться с этим, я использовал полиморфные отношения Laravel для работы с различными типами настроек. Я создал модель Setting, использующуюся для работы с различными типами настроек.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Setting extends Model
{
public function notification()
{
return $this->morphTo('type', 'type', 'id');
}
}

Метод notification — полиморфное отношение, возвращающее правильную модель на основе столбца type таблицы настроек.

Чтобы указать Laravel, какую модель использовать для каждого типа, необходимо добавить morphMap в класс AppServiceProvider.

<?php

namespace App\Providers;

class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Relation::morphMap([
'email' => EmailSetting::class,
'slack' => SlackSetting::class,
]);
}
}

Метод morphMap сопоставит типы email и slack с классами EmailSetting и SlackSetting соответственно.

Теперь при получении параметра из базы данных можно получить доступ к нужной модели на основе столбца type.

$setting = Setting::find(1);

if($setting->type === 'email') {
$email = $setting->notification->getEmail();
}

if($setting->type === 'slack') {
$channel = $setting->notification->getChannel();
$token = $setting->notification->getToken();
}

Но при этом вы получите ошибку, когда попытаетесь использовать ->notification, так как он попытается получить доступ к несуществующей таблице email_settings.

Чтобы исправить это, необходимо указать модели EmailSetting, какую таблицу использовать методу getTable.

public function getTable()
{
return 'settings';
}

Это позволит модели EmailSetting использовать таблицу settings вместо email_settings и возвращать правильную модель при использовании настроек уведомлений.

Вот как можно использовать полиморфные модели по типу в Laravel для обработки различных типов настроек в одной таблице базы данных. Это может быть полезным, когда в приложении необходимо обрабатывать различные типы настроек.

Надеюсь, эта статья помогла вам понять, как использовать полиморфные модели по типу в Laravel.

Дополнительные материалы

Предыдущая Статья

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

Следующая Статья

Создание виртуального столбца в базе данных в Laravel