В моем проекте Laravel есть три разные модели; Конвой, Пользователь, Водитель. Модель драйвера отличается от модели пользователя, поскольку они не могут пройти аутентификацию. Как бы то ни было, есть еще одна модель: Адрес.
Я храню значения адресов в таблице addresses
модели адреса. Столбцы приведены ниже;
addresses
: addressable_type (int)
, addressable_id (int)
...
Есть еще одна модель под названием Type, она хранит типы всего, что есть в проекте. Например, он хранит типы авторизации (Суперпользователь, Пользователь, Администратор и т. д.), красноречивые типы моделей, которые указаны в пути Models\ (App\Models\User, App\Models\Driver и т. д.), платежи. типы и т. д.
Я думаю, ты понял, о чём я тебя спрошу, но давай продолжим. Если вы разобрались, я не задавал тип addresses
.addressable_type
как varchar(255)
. Обычно полиморфная модель может читать формат App\Models\*
, но вместо этого я хочу сохранить идентификатор красноречивой модели из таблицы types
.id
.
addressable_type | 10 // this refers to `types`.`id`
addressable_id | 1
country | 225
state | 2175
city | 108155
address | NULL
status | 1
created_at | 2024-08-31 14:50:13
updated_at | 2024-08-31 14:50:13
id | 10
type | App\Models\Convoy // so this is record in the types table
label | 2
created_at | 2024-08-31 14:50:12
updated_at | 2024-08-31 14:50:12
Convoy.php приведен ниже;
class Convoy extends Model
{
use HasFactory;
protected $guarded = [];
public function address() : MorphOne
{
return $this->morphOne(Address::class, 'addressable');
}
}
Address.php указан ниже;
class Address extends Model
{
use HasFactory;
protected $guarded = [];
public function addressable() : MorphTo
{
return $this->morphTo();
}
public function status() : BelongsTo
{
return $this->belongsTo(Status::class);
}
}
HomeController.php, указанный ниже;
public function convoys() : View
{
$test = Convoy::with('address')->find(6);
dd($test);
return view('convoys', compact('convoys'));
}
Результат;
App\Models\Convoy {#1228 ▼ // app/Http/Controllers/HomeController.php:50
...
#relations: array:1 [▼
"address" => null
]
...
}
Я не могу получить какой-либо адрес.
Когда я получаю запись Convoy с заданным кодом $test = Convoy::with('address')->find(6);
, она возвращает запись Convoy с идентификатором = 6. Мне нужны данные адреса из таблицы адресов. А строка «App\Models\Convoy» хранится в таблице типов, и эта запись имеет идентификатор (например, 15). Я хочу сказать полиморфной системе: «Не ищите App\Models\Convoy в таблице адресов, ищите 15». Итак, я хочу трансформироваться в поисках идентификатора типа в таблице типов.
Просто из любопытства, почему бы вам не использовать type и type_id в полиморфном отношении? Они будут работать как составной ключ, поэтому вам не нужно будет использовать столбец id для получения данных.
вы можете обновить AppServiceProvider и добавить это
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
10 => App\Models\Convoy::class,
11 => App\Models\User::class,
12 => App\Models\Driver::class,
]);
Это не сработало. Когда я говорю о Convoy.php; public function address() { return $this->morphOne(Address::class, 'addressable'); }
он ищет where addressable_type = 'App\Models\Convoy'
, но я хочу изменить этот запрос, сначала просматривая идентификатор (например, 15) значения «App\Models\Convoy» в таблице типов, а затем заменяя это значение идентификатора в запросе. where addressable_type = 15
Я обновил ответ, пожалуйста, проверьте его
Так что спасибо, Хамдалла, ты лучший!
Я бы рекомендовал вам использовать полиморфные отношения по назначению.
В качестве полиморфных отношений у вас будет следующее:
<?php
class Address extends Model
{
public function parent(): MorphTo
{
return $this->morphTo();
}
}
Затем я бы рекомендовал вам использовать признак, чтобы прикрепить его к любым моделям, с которыми будет связан адрес (это поможет предотвратить дублирование кода).
<?php
trait HasAddress {
public function address(): MorphOne
{
return $this->morphOne(Address::class);
}
}
Затем внутри вашего Конвоя, Пользователя, Водителя или чего-либо еще, у которого будет адрес, вы можете просто добавить следующее в его начало.
use HasAddress;
Вам нужно следовать определенной структуре модели или это ваша собственная установка? Я бы рекомендовал вам хранить всех ваших пользователей, используя модель пользователя, а затем настроить другую, которая будет управлять их разрешениями/ролями.