#php #laravel #eloquent
#php #laravel #красноречивый
Вопрос:
Я получил пользовательскую модель, которая связана с рабочими условиями, которые связаны с подобными сервисами:
users working_terms services
id -> user_id
service_id <- id
active(1 or 0)
Я создал метод в своей пользовательской модели, чтобы получить сервис активного рабочего термина таким образом
public function service()
{
return $this
->belongsToMany(Service::class,'working_terms')
->where('active','=',1);
}
Проблема в том, что я должен использовать ее таким образом в представлениях $user-> service[0], на мой взгляд, это должно быть $user-> service.
Что я могу сделать?
Комментарии:
1. вам нужно взглянуть на это laravel.com/docs/8.x/eloquent-relationships#has-many-through
2. Я просто хочу ОДНУ запись, основанную на логических критериях, а не на массиве
3. Если пользователь не может быть связан с более чем одним сервисом (например, путем добавления другой строки в сводную таблицу с тем же идентификатором пользователя, но с другим идентификатором service_id), вам необходимо пересмотреть дизайн вашей базы данных и сделать соотношение «один ко многим» или «один к одному».
4. У одного пользователя может быть несколько рабочих терминов, но активен только один, и у каждого рабочего термина есть одна услуга, я не думаю, что это проблема проектирования базы данных. working_terms на самом деле является сводной таблицей
Ответ №1:
Когда Laravel оценивает $user->service
, сначала он определяет, является ли возвращаемое значение $user->service()
экземпляром IlluminateDatabaseEloquentRelationRelation
класса, и если нет, то выдает ошибку. Ваш service()
метод возвращает IlluminateDatabaseQueryBuilder
вместо Relation
, поэтому ваш фрагмент $user->service
не возвращает нужную вам модель сервиса.
Для получения более подробной информации см. Эту ссылку; https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L432
Ответ №2:
belongsToMany
Связь возвращает Eloquent Collection
независимо от того, предоставляете ли вы where
предложение как часть отношения. Поэтому вы захотите использовать first()
для получения первого (и единственного?) запись.
На стороне Laravel есть соглашение об именовании для сводных таблиц (хотя я уверен, что у вас есть свои причины для выбора имен, которые у вас есть).
User.php
public function services()
{
return $this->belongsToMany(Service::class)
->withTimestamps();
}
public function getActiveServiceAttribute()
{
return $this->services()
->wherePivot('active', 1)
->first();
}
Вышесказанное делает предположение, что я следую соглашениям об именах Laravel, в которых сводная таблица между таблицами users
и services
называется service_user
.
create_service_user_table.php
public function up()
{
Schema::create('service_user', function(Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('user_id');
$table->foreignId('service_id');
$table->unsignedTinyInteger('active')->default(0);
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('service_id')->references('id')->on('services');
});
}
Поскольку вы не соблюдаете соглашения об именовании Laravel, вам нужно будет указать имя вашей сводной таблицы в качестве второго аргумента belongsToMany
отношения в services()
функции (или, если возможно, измените имя сводной таблицы и следуйте соглашениям).
Теперь вы должны быть в состоянии делать такие вещи, как:
// obtain a collection of all services the User has been associated with
User::find(1)->services
// obtain the currently active service for the User
User::find(1)->activeService