Модель Laravel, получающая только одну связанную модель

#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