I've entered the fantastic world of Laravel and I am currently looking into seeding a database with fake data for testing.
I have a couple of tables I want to work with; projects and stories.
The stories table has the columns; id, name and project_id (which is a fk to the projects table).
My projects table is already populated with a list of 10 projects. Now I need to populate 100 stories with random projects associated. I have the approach below.
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')
]);
}
}
I don't know if this is the best way of doing what I need. However, when performing this code every story's project_id is set to 1; the first project's id.
When I perform the following command in tinker... It always returns 1 as the id.
Project::orderBy(\DB::raw('RAND()'))->get()->first()->pluck('id')
But when I perform the next command in tinker...
Project::orderBy(\DB::raw('RAND()'))->get()->first()
It returns a random project every time. Which is strange. Because if everything up to ->pluck() is working then pluck() should fetch that collected items id... Right? This is what the above command returns.
<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" }
See below screenshot for my terminal window to illustrate what I mean.
Here's what's happening:
With ->first()
you get the actual project model
Then you call pluck('id')
on it. BUT the Model
class doesn't have that method.
So with, as with every method the Model
doesn't know, it redirects the call to a new query builder instance of the model.
In the end, that call ends up here:
Illuminate\Database\Eloquent\Builder@value
public function value($column)
{
$result = $this->first(array($column));
if ($result) return $result->{$column};
}
As you can see, that method runs a new query, using first()
and then returns the desired row.
Now what you actually want is either:
pluck
at allThere isn't really a need to use that method, you can just access the model property:
'project_id' => Project::orderBy(\DB::raw('RAND()'))->first()->id
pluck
, but do it right'project_id' => Project::orderBy(\DB::raw('RAND()'))->pluck('id')
And btw, the main method is called value()
. pluck()
is just an alias. I recommend using value()
in new code. It's possible that the alias will be removed some day. (Obviously just in a new release and with a note in the upgrade guide, so don't panic ;))