1

Given that I have the following tables:

  • users
  • questions
  • tags
  • question_tag my pivot table with two fields: question_id & tag_id

and my App\Question model has the following relationships:

class Question extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function tags()
    {
        return $this->hasMany(Tag::class);
    }
}

I've created the following factories:

database/factories/UserFactory.php

$factory->define(App\User::class, function (Faker $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('123456')
    ];
});

database/factories/QuestionFactory.php

$factory->define(App\Question::class, function (Faker $faker) {
    static $user_id;

    return [
        'user_id' => $user_id,
        'subject' => $faker->sentence(15),
        'body' => $faker->paragraph(10)
    ];
});

database/factories/TagFactory.php

$factory->define(App\Tag::class, function (Faker $faker) {
    return [
        'name' => str_slug($faker->words(mt_rand(1, 2))),
        'description' => $faker->sentence()
    ];
});

I tried to use it all together in my dummy data seeder like this:

class DummyDataSeeder extends Seeder
{
    public function run()
    {
        // Seed dummy users
        factory(App\User::class, 10)->create()->each(function($user)
        {
            // With dummy questions
            $user->questions()->saveMany(factory(App\Question::class, 10)->make()->each(function($question)
            {
                // With dummy tags
                $question->tags()->sync(factory(App\Tag::class, 3)->make());
            }));
        });
    }
}

When I run the seeder, I get the following error:

[ErrorException] mb_strtolower() expects parameter 1 to be string, array given

Is this not possible to do in model factory? Do I need to use a different approach?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Latheesan
  • 23,247
  • 32
  • 107
  • 201

2 Answers2

0

I think you need to use belongsToMany for your pivot Table

In Your Question model

public function tags()
 {
  return $this->belongsToMany(Tag::class,'question_tag','tag_id','question_id');
 }

same with your Tag Model

public function questions()
{
 return $this->belongsToMany(Question::class,'question_tag','question_id','tag_id');
}

also, You need to change

 $question->tags()->sync(factory(App\Tag::class, 3)->make());

to

$tags = factory(App\Tag::class, 3)->make();
$tagIds = Tag::select('id')->get()->toArray();
 $question->tags()->sync($tagIds);

which means you need to pass IDs in Sync argument.

ankit patel
  • 1,888
  • 11
  • 12
0

From fzaninotto/Faker readme:

words($nb = 3, $asText = false) // array('porro', 'sed', 'magni').

will return array

Laravel str_slug()

The str_slug function generates a URL friendly "slug" from the given string: $slug = str_slug('Laravel 5 Framework', '-');

str_slug expects string

In your database/factories/TagFactory.php you need to fix the line:

'name' => str_slug($faker->words(mt_rand(1, 2))),

to

'name' => str_slug(implode(' ', $faker->words(mt_rand(1, 2)))),

or maybe

'name' => str_slug($faker->sentence(mt_rand(1, 2))),
ljubadr
  • 2,174
  • 1
  • 20
  • 24
  • Okay, the error was caused by the incorrect faker usage, not the migration. I have corrected it in my factory like this: `'name' => str_slug($faker->words(mt_rand(1, 2), true), '-'),` - now I am getting a different error: `Call to undefined method Illuminate\Database\Query\Builder::sync()` – Latheesan Oct 24 '17 at 09:46
  • @Latheesan - I answered the original question (before it was edited), but you should avoid changing the question after getting the answer. Best thing would be to create a new question. – ljubadr Oct 24 '17 at 15:17