Laravel 5 получает первую запись в wherepivot

У меня есть 3 таблицы:

*document* [id, core_document]  
*person* [id, name]  
*documentPersonsRole* [document_id, person_id, role] (where role could be accused or victim) 

Можно ли создать быстрый метод для возврата первой записи из отношения «принадлежит многим»? Вот мой код из файла модели:

public function documentPersonsRole()
{
    return $this->belongsToMany('App\Models\Person', 'document_person_role')
        ->withPivot('role')
        ->withTimestamps();
}

public function accused()
{
    return $this->belongsToMany('App\Models\Person', 'document_person_role')
        ->withPivot('role')
        ->wherePivot('role', 'accused')
        ->withTimestamps();
}

public function victim()
{
    return $this->belongsToMany('App\Models\Person', 'document_person_role')
            ->withPivot('role')
            ->wherePivot('role', 'victim')
            ->withTimestamps();    
}

Когда я это называю:

App\Models\Document::with('accused')->first()
=> App\Models\Document {#3118
     id: 1,
     core_document: "Iure aut eum aut ex et. Magni aliquam illo voluptatem non repellat. Maxime occaecati reiciendis veniam quod neque reiciendis dolores. Eaque quis molestiae dolorem. Et rerum veniam animi sit beatae inventore voluptas. Aut ea atque nulla quis quam incidunt iusto voluptas. Aut corrupti voluptas minima unde dicta vero aut veritatis. Voluptas vitae nam mollitia quasi porro id quod ut.",         
     accused: Illuminate\Database\Eloquent\Collection {#3127
       all: [
         App\Models\Person {#3139
           id: 41,
           name: "Jamie",               
           pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3138
             document_id: 1,
             person_id: 41,
             role: "accused",
             created_at: "2018-10-24 03:55:23",
             updated_at: "2018-10-24 03:55:23",
           },
         },
       ],
     },
   }

И вы можете видеть, что обвиняемый - это коллекция только с одной записью, и когда я получаю ее на стороне клиента, мне нужно извлечь эту запись из массива, но я хочу работать с объектом.

Когда я пробую что-то вроде этого:

public function accused()
    {
        return $this->belongsToMany('App\Models\Person', 'document_person_role')
            ->withPivot('role')
            ->wherePivot('role', 'accused')
            ->withTimestamps()->first();
    }

Я получаю вот такую ​​ошибку:

BadMethodCallException с сообщением «Вызов неопределенного метода Illuminate / Database / Query / Builder :: addEagerConstraints ()»

Как я могу использовать first () для извлечения и объекта в обвиняемом вместо массива с одной записью.

Не совсем уверен, но пробовали ли вы belongsToOne вместо belongsToMany?

i-- 26.10.2018 05:37

@ i ... Я почти уверен, что belongsToOne() не существует

Travis Britz 26.10.2018 05:50
->belongsTo()?
i-- 26.10.2018 05:53
1
3
658
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Как вы к нему обращаетесь?

Возможно, вам придется вызвать метод напрямую, вместо того, чтобы позволить Laravel попытаться динамически получить его с помощью магического метода:

$accused = $document->accused()

Или определите аксессуар:

public function getAccusedAttribute() {
    return $this->belongsToMany('App\Models\Person', 'document_person_role')
        ->withPivot('role')
        ->wherePivot('role', 'accused')
        ->withTimestamps()
        ->first();
}

Что позволит вам использовать $accused = $document->accused;

Обычно, когда вы определяете метод bar(), который возвращает связь, при вызове $foo->bar Laravel подключает магический метод __get() в PHP для вызова bar()->get() где-то за кулисами. Поскольку вы уже выполняете запрос, используя first() для отношения, Laravel ожидал, что отношение будет запускать запрос, но в итоге получил вашу модель.

Редактировать:

Если вам все еще нужна возможность загружать отношения, вот еще один метод:

В документе:

public function accusedPeople()
{
    return $this->belongsToMany('App\Models\Person', 'document_person_role')
        ->withPivot('role')
        ->wherePivot('role', 'accused')
        ->withTimestamps();
}

public function getFirstAccusedAttribute()
{
    return $this->accusedPeople
        ->first();
}

В контроллере:

// If you're eager loading, the relationship to eager load is `accusedPeople`
$document = Document::with('accusedPeople')->first();

// The accused person is accessed with the `first_accused` property
$accused = $document->first_accused;

// if you're returning the model directly for json:
// $document->append('first_accused');

Мне это нравится, но оказывается, что я делаю это неправильно. getAccusedAttribute () - эта функция позволяет использовать это и извлекать отношение: $ document-> обвиняемый Спасибо! Но как мне использовать его в контроллере вместо этого индекса общедоступной функции (Request $ request) {$ query = Document :: with ('обвиняемый'); $ documents = $ query-> get (); return response () -> json ($ documents, 200); } Использовать после получения данных о клиенте: $ document-> обвиняемый

Maxim Stogniy 26.10.2018 06:49

@MaximStogniy извините, я не уверен, что говорится в вашем комментарии?

Travis Britz 26.10.2018 06:51

Исправлю свой комментарий, поможете?

Maxim Stogniy 26.10.2018 07:16

@MaximStogniy, вы не можете загружать его в текущем виде (нельзя использовать with('accused'))

Travis Britz 26.10.2018 07:23

Есть идеи, как я могу собрать объектный документ, который включает, например, [id, core_document, обвиняемый (объект)]? Или единственный вариант - это массив с одним элементом, который нужно будет преобразовать в объект на клиенте?

Maxim Stogniy 26.10.2018 07:27

@MaximStogniy Я обновил ответ, это вообще помогает?

Travis Britz 26.10.2018 07:30

К сожалению, все еще массив

Maxim Stogniy 26.10.2018 07:42

@MaximStogniy что такое массив?

Travis Britz 26.10.2018 07:43

Если я все сделаю правильно, он содержит один элемент - обвиняемого.

Maxim Stogniy 26.10.2018 07:45

$ document-> first_accused вернет одну модель человека из документа. В моем примере с контроллером я использовал Document :: get () вместо Document :: first (), чтобы я мог продемонстрировать, как он используется с нетерпеливой загрузкой, где вы получаете массив (документов)?

Travis Britz 26.10.2018 07:49

Но у меня такой вопрос: $ accused = $ document-> first_accused; Я думаю, что это ошибка, и правильно будет так: $ document-> test = $ document-> first_accused;

Maxim Stogniy 26.10.2018 07:49

@MaximStogniy вы превращаете это в json? Возможно, вам потребуется выполнить $document->append('first_accuser'), если вы хотите, чтобы он отображался в ответе

Travis Britz 26.10.2018 07:59

Да, я превращаюсь в json. Ваш способ добавления хорош, я воспользуюсь им)

Maxim Stogniy 26.10.2018 09:30

попробуй это:

App\Models\Document::with(['accused' => function($query){
    $query->first();
}])->first()

это запросит у accused возврат только 1-й строки.

По-прежнему возвращает массив $ vm0.documents [0] .accused [{…}, ob: Observer] 0: {…} length: 1 ob: Observer {value: Array (1), dep: Dep, vmCount: 0} прото : Множество

Maxim Stogniy 26.10.2018 06:38

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