Почему $ this пусто при использовании load () в laravel eloquent? - PullRequest
0 голосов
/ 28 февраля 2020

Итак, у меня есть эти 2 таблицы

components
=========================
| id | code | type      |
=========================
|  1 | E1   | Engine    |
|  2 | G1   | Generator |
|  3 | E2   | Engine    |
=========================

formulas /* engine_id and generator_id reference to component id */
=============================================
| id | engine_id | generator_id | diesel_id |
=============================================
|  1 |         1 |            2 |         1 |
|  2 |         3 |            2 |         1 |
=============================================

Итак, в Model / Component. php, я создал эту красноречивую функцию

public function formulas()
{
    $foreignKey = $this->type === 'Engine' ? 'engine_id' : 'generator_id';

    return $this->hasMany(Formula::class, $foreignKey);
}

Она отлично работает, если я использую $component->formulas. Но я должен назвать дизель для каждой формулы тоже. Я не люблю использовать load () внутри al oop.

// ComponentController.php
public function show(Component $component)
{
    $component->formulas->each(function ($formula) {
        //if this component has 100 formulas, then it will do 100 query to table diesels
        $formula->load('diesel');
    });

    return $component;
}

Так что я хочу использовать $component->load('formulas.diesel'), но $this всегда пуст и внешний ключ всегда будет установлен как 'generator_id'

// Component.php
public function formulas()
{
    $foreignKey = $this->type === 'Engine' ? 'engine_id' : 'generator_id';
    info($this); // this will be called twice, but only first call has value.

    return $this->hasMany(Formula::class, $foreignKey);
}

// ComponentController.php
public function show(Component $component)
{
    info('=== 1 ===');
    $component->formulas;
    info('=== 2 ===');

    return $component->load('formulas');
}

// Outputs in Laravel.log
[2020-02-28 18:15:08] testing.INFO: === 1 ===  
[2020-02-28 18:15:08] testing.INFO: {"id":1,"code":"E1","type":"Engine"}  
[2020-02-28 18:15:08] testing.INFO: === 2 ===  
[2020-02-28 18:15:08] testing.INFO: []  <------ why is this empty??

1 Ответ

0 голосов
/ 06 марта 2020

Использование функций -> with () или -> load (), вызываемых Eager Loading . Он предназначен для решения проблемы N + 1.

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

select * from formulas where engine_id = 1
select * from formulas where generator_id = 2
...

. Будет вызван один запрос для всех моделей. используя их идентификаторы, такие как:

select * from formulas where generator_id in (1, 2, 3, ...)

В этом отношении вы не можете использовать «this», потому что функция Formulas () будет вызываться из «пустого экземпляра» вашей модели Component просто для идентификации отношения.

Чтобы лучше понять, вы можете прочитать документацию о Eager Загрузка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...