Метод сбора Laravel не работает должным образом

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

У меня есть пара таблиц, с которыми я хочу поработать; проекты и рассказы.

В таблице историй есть столбцы; id, name и project_id (который является fk для таблицы проектов).

Таблица Мои проекты уже заполнена списком из 10 проектов. Теперь мне нужно заполнить 100 историй случайными связанными проектами. У меня есть подход ниже.

public function run()
{
    DB::table('stories')->delete();
    DB::statement('ALTER TABLE stories AUTO_INCREMENT = 1');

    $faker = Faker::create();

    foreach(range(1, 100) as $index)
    {
        Story::create([
            'reference' => $faker->numberBetween(1, 9999),
            'name' => $faker->sentence(6),
            'project_id' => Project::orderBy(\DB::raw('RAND()'))->get()->first()->pluck('id')
        ]);
    }
}

Не знаю, лучший ли это способ делать то, что мне нужно. Однако при выполнении этого кода project_id каждой истории устанавливается в 1; идентификатор первого проекта.

Когда я выполняю следующую команду в tinker ... Она всегда возвращает 1 в качестве идентификатора.

Project::orderBy(\DB::raw('RAND()'))->get()->first()->pluck('id')

Но когда я выполняю следующую команду в tinker ...

Project::orderBy(\DB::raw('RAND()'))->get()->first()

Он каждый раз возвращает случайный проект. Что странно. Потому что, если все до -> pluck () работает, то pluck () должен получить идентификатор собранных элементов ... Верно? Это то, что возвращает приведенная выше команда.

<App\Project #000000000c385908000000000de30942> {
   id: 6,
   name: "New Bernadetteton",
   cover_photo_url: "/uploads/covers/horizon-grass.png",
   created_at: "2015-07-08 16:32:15",
   updated_at: "2015-07-08 16:32:15" }

Смотрите ниже снимок экрана моего окна терминала, чтобы проиллюстрировать, что я имею в виду.

введите описание изображения здесь


person Brad Bird    schedule 08.07.2015    source источник


Ответы (1)


Вот что происходит:

  1. С ->first() вы получаете актуальную модель проекта

  2. Затем вы звоните pluck('id'). НО у класса Model нет этого метода.

  3. Таким образом, как и в случае с любым другим методом, Model не знает, он перенаправляет вызов на новый экземпляр модели построителя запросов.

  4. В конце концов, этот звонок заканчивается здесь:

Illuminate\Database\Eloquent\Builder@value

public function value($column)
{
    $result = $this->first(array($column));

    if ($result) return $result->{$column};
}

Как видите, этот метод запускает новый запрос, используя first(), а затем возвращает нужную строку.


Теперь то, что вам действительно нужно, это либо:

1. Не используйте pluck вообще

На самом деле нет необходимости использовать этот метод, вы можете просто получить доступ к свойству модели:

'project_id' => Project::orderBy(\DB::raw('RAND()'))->first()->id

2. Используйте pluck, но делайте правильно

'project_id' => Project::orderBy(\DB::raw('RAND()'))->pluck('id')

И, кстати, основной метод называется value(). pluck() - это просто псевдоним. Я рекомендую использовать value() в новом коде. Возможно, когда-нибудь псевдоним будет удален. (Очевидно, только в новом выпуске и с примечанием в руководстве по обновлению, так что не паникуйте;))

person lukasgeiter    schedule 08.07.2015
comment
Спасибо! Сработало отлично. Теперь я вызываю - ›id в методе -› first () напрямую. Я понятия не имел, что он ссылается на модель, и просто подумал, что он стер результат, установленный до 1 (первый объект). - person Brad Bird; 08.07.2015