Могу ли я изменить столбец типа в полиморфном отношении Laravel?

В моем проекте 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
  ]
  ...
}

Я не могу получить какой-либо адрес.

Вам нужно следовать определенной структуре модели или это ваша собственная установка? Я бы рекомендовал вам хранить всех ваших пользователей, используя модель пользователя, а затем настроить другую, которая будет управлять их разрешениями/ролями.

LewBlu 31.08.2024 21:46

Когда я получаю запись Convoy с заданным кодом $test = Convoy::with('address')->find(6);, она возвращает запись Convoy с идентификатором = 6. Мне нужны данные адреса из таблицы адресов. А строка «App\Models\Convoy» хранится в таблице типов, и эта запись имеет идентификатор (например, 15). Я хочу сказать полиморфной системе: «Не ищите App\Models\Convoy в таблице адресов, ищите 15». Итак, я хочу трансформироваться в поисках идентификатора типа в таблице типов.

Beresyus 31.08.2024 21:57

Просто из любопытства, почему бы вам не использовать type и type_id в полиморфном отношении? Они будут работать как составной ключ, поэтому вам не нужно будет использовать столбец id для получения данных.

LewBlu 31.08.2024 22:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
3
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

вы можете обновить 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

Beresyus 31.08.2024 21:57

Я обновил ответ, пожалуйста, проверьте его

Hamdallah 31.08.2024 22:15

Так что спасибо, Хамдалла, ты лучший!

Beresyus 31.08.2024 22:21

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

<?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;

Другие вопросы по теме