itwolfpower
itwolfpower

Reputation: 316

Laravel 7: Create a custom factory for category

I was trying to make the following category factory to work.

Category factory

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Category;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

$categories = ['category', 'category-2', 'category-3']

$factory->define(Category::class, function (Faker $faker) {
    return [
        'name' => // I can't use a foreach here
        'slug' => Str::slug($category),
    ];
});

How do I implement this?

I need my categories to be unique

Update Using the latest update from @omr

Category factory

use App\Category;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

$categories = ['Hardware', 'Software', 'Planning', 'Tools'];

foreach ($categories as $categoryName) {
    factory(Category::class)->create([
        'name' => $categoryName,
        'slug' => Str::slug($categoryName),
    ]);
}

Database seeder



public function run()
    {
        factory('App\Category', 20)->create();
        
    }

 ErrorException 

  require(/home/dan/Codes/laravel/jobportal/database/factories/CategoryFactory.php): failed to open stream: Too many open files

  at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factory.php:220
    216|         $factory = $this;
    217| 
    218|         if (is_dir($path)) {
    219|             foreach (Finder::create()->files()->name('*.php')->in($path) as $file) {
  > 220|                 require $file->getRealPath();
    221|             }
    222|         }
    223| 
    224|         return $factory;
 

Thanks

Upvotes: 2

Views: 7536

Answers (2)

Aminul Islam
Aminul Islam

Reputation: 73

You will need a database seeder.

You category factory will be like as below:

$factory->define(Category::class, function (Faker $faker) {
    return [
        'name' => 'Name',
        'slug' => 'name',
    ];
});

And your database seeder will be:

$categories = ['Category', 'Category 2', 'Category 3'];

foreach($categories as $category) {
  factory(App\Category::class)->create([
    'name' => $category,
    'slug' => \Str::slug($category)
  ]);
}

Now run: php artisan db:seed (Note: this will seed all other seeders, better use: --class=YOUR_SEED_CLASS)

Upvotes: 1

OMR
OMR

Reputation: 12188

you can use $faker->numberBetween to get random element from $categories array and then use it inside the factory:

$categories = ['category', 'category-2', 'category-3'];

$factory->define(Category::class, function (Faker $faker)use($categories) {
    $categoryName= $categories[$faker->numberBetween(0,count($categories)-1)];
    return [
        'name' =>$categoryName,
        'slug' => Str::slug($categoryName),
    ];
});

edit:

if you want to generate unique category names

first: standard category factory:

$factory->define(Category::class, function (Faker $faker){

    return [
        'name' =>$faker->name,
        'slug' =>  Str::slug($faker->text(12))
    ];
});

as long as you pass the factory fields you self, there is no need for worrying about category name and slug compatibility ....

second:

now when you make your categories you pass the attributes you want, like this:

in Database seeder:

use use Faker\Generator;

....... .......

$counter=0;
while($counter<20)
{
$categoryName=$faker->text(12);
if(Category::firstWhere('name',$categoryName)==null)
{
$counter+=1;
factory(Category::class)->create(['name'=>$categoryName,'slug'=>Str::slug($categoryName)]);
}
}

don't use directly factory('App\Category', 20)->create(); with no parameter it can't help you there ...

Upvotes: 2

Related Questions