Могу ли я изменить столбец типа в полиморфном отношении 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
  ]
  ...
}

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

🤔 А знаете ли вы, что...
PHP имеет встроенную поддержку сессий для отслеживания состояния пользователей на веб-сайтах.


1
61
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,
    ]);

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

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

Интересные вопросы для изучения