Error in using PHP fakers - php

I am trying to seed data as provided in this link https://github.com/fzaninotto/Faker. The tables are filled but but I got this error:
$ php artisan db:seed
Seeding: gamesSeeder
Method Illuminate\Database\Query\Builder::issues does not exist.
I am running Lumen (5.6.3) (Laravel Components 5.6.*).
<?php
$factory->define(App\teams::class, function (Faker\Generator $faker) {
return [
'name' => $faker-> word,
];
});
$factory->define(App\games::class, function (Faker\Generator $faker) {
return [
'Team 1' => $faker-> word,
'Team 2' => $faker-> word,
'Score 1' => $faker->numberBetween($min = 0, $max = 10),
'Score 2' => $faker->numberBetween($min = 0, $max = 10),
'Game Date' => $faker->date($format = 'Y-m-d', $max = 'now'),
'Viewers' => $faker-> numberBetween($min = 0, $max = 100000),
];
});
Here are my seeders files.
teamsSeeder:
<?php
use Illuminate\Database\Seeder;
class gamesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\games::class, 30)->create()->each(function($u) {
$u->issues()->save(factory(App\games::class)->make());
});
}
}
and here is gamesSeeder
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use App\teams;
class teamsSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\teams::class, 5)->create()->each(function($u) {
$u->issues()->save(factory(App\teams::class)->make());
});
}
}

Related

Laravel NotificationFake.php sendNow causes Illegal offset type error when notifiable->id is an uuid

I am using Laravel 9, Vue 3 and Inertia.
I have created the following test:
public function test_send_notification(): void
{
Notification::fake();
$this->seed(OccupationSeeder::class);
$responder = Responder::factory()->create();
$responder->notify(new InviteResponder());
Notification::assertSentTo($responder, InviteResponder::class);
}
When I run the test I am getting
TypeError : Illegal offset type
It fails when executing
$this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
'notification' => $notification,
'channels' => $notifiableChannels,
'notifiable' => $notifiable,
'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
if ($notifiable instanceof HasLocalePreference) {
return $notifiable->preferredLocale();
}
}),
];
in NotificationFake.php sendNow()
Here is part of my Responder model
class Responder extends Model
{
use HasFactory, Notifiable;
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public $incrementing = false;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'uuid',
'diagnostic_event_id',
'school_id',
'user_id',
'occupation_id',
'years',
'status'
];
/**
* Autogenerate uuid
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::creating(function($model) {
// Automatically create an uuid when creating a new responder
$model->setAttribute($model->getKeyName(), Str::uuid());
});
}
and here is ResponderFactory
class ResponderFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition()
{
return [
'uuid' => $this->faker->uuid,
'diagnostic_event_id' => DiagnosticEvent::factory()->lazy(),
'school_id' => School::factory()->lazy(),
'user_id' => User::factory()->lazy(),
'occupation_id' => $this->faker->numberBetween(1,13),
'years' => $this->faker->numberBetween(1,5),
'status' => 'created',
'created_at' => now(),
'updated_at' => now()
];
}
}
When I call $responder->notify(...) in my program, I get no error.
Here is my ResponderController invite() function that works:
public function invite(Request $request): RedirectResponse
{
$this->authorize('create', Responder::class);
$responders = Responder::where('diagnostic_event_id', $request->diagnostic_event_id)->get();
$questions = Question::all();
DB::transaction( function() use ($request, $responders, $questions) {
foreach ($responders as $responder) {
// Skip if responder already notified
if ($responder->status === 'created') {
// Create null answers for the responder if not already exists
foreach ($questions as $question) {
Answer::create([
'diagnostic_event_id' => $request->diagnostic_event_id,
'responder_uuid' => $responder->uuid,
'question_id' => $question->id,
'score' => null
]);
}
// Send notification to responder
$responder->notify(new InviteResponder());
// Update responder status
$responder->update(['status' => 'sent']);
}
}
});
return redirect()->route('responder.select',
['event_id' => $request->diagnostic_event_id]);
}
What is wrong with my test and what can I do to fix this?
You may want to change your faker to this:
'uuid' => Str::ulid()->toBase32()
Or simply:
'uuid' => $this->newModel()->newUniqueId()

Use faker in laravel when inserting thousand of records

I have one issue with laravel faker, I was looking for a tutorial to insert thousands of records using seeders
This was my PostSeeder.php:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\User;
class PostSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Post::factory(10)->create();
}
}
Here I was inserting 10 posts, but I need to test thousands or millions of records, so I saw a tutorial and modified the seeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Str;
class PostSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$users= collect(User::all()->modelKeys());
$data = [];
for ($i = 0; $i < 100000; $i++) {
$data[] = [
'body' => Str::random(50),
'image' => 'https://via.placeholder.com/640x480.png/0077dd?text=inventore',
'user_id' => $users->random(),
'created_at' => now()->toDateTimeString(),
'updated_at' => now()->toDateTimeString(),
];
}
$chunks = array_chunk($data, 10000);
foreach ($chunks as $chunk) {
Post::insert($chunk);
}
}
}
With this approach I can insert thousand of records faster, but the problem is that I am not inserting correctly the body and image field
I wanted to try something with faker, in my factory I have this:
PostFactory.php
<?php
namespace Database\Factories;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Post::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'body' => $this->faker->text,
'image' => $this->faker->imageUrl(),
'user_id' => function() {
return User::factory()->create()->id;
}
];
}
}
I would like to use faker methods like these ones in the PostSeeder but I can't, what can I do? thank you.
EDIT:
I tried this:
public function run(Faker $faker)
{
$users= collect(User::all()->modelKeys());
$data = [];
for ($i = 0; $i < 50000; $i++) {
$data[] = [
'content' => $faker->text,
'image_path' => $faker->imageUrl(),
'user_id' => $users->random(),
'created_at' => now()->toDateTimeString(),
'updated_at' => now()->toDateTimeString(),
];
}
$chunks = array_chunk($data, 5000);
foreach ($chunks as $chunk) {
Post::insert($chunk);
}
}
And I got this message:
PDOException::("SQLSTATE[HY000]: General error: 2006 MySQL server has gone away")
But when I try with fewer records it works, so, I changed the seeder like this:
$users= collect(User::all()->modelKeys());
$posts = Post::factory(10)->create();
$posts = collect($posts->only(['content','image_path']));
...
...
'content' => $posts->random()->content,
'image_path' => $posts->random()->image_path
...
and this doesn't work, it got this error:
You requested 1 items, but there are only 0 items available.
It looks like $posts->only(['content','image_path']) is not working properly. So I tried this:
Post::factory(10)->create();
$tweets = Tweet::select(['content','image_path'])->get();
...
'content' => $posts->random()->content,
'image_path' => $posts->random()->image_path
...
And again it works with a few records, but when I try with thousands, I get this error again:
PDOException::("SQLSTATE[HY000]: General error: 2006 MySQL server has gone away")
What can I do? thank you
Since model factories create in-memory objects, because of big memory usages it is not suitable for large seeds.
But you can use Faker for data generation:
use Faker\Generator as Faker;
class PostSeeder extends Seeder
{
public function run(Faker $faker)
{
$users= collect(User::all()->modelKeys());
$data = [];
for ($i = 0; $i < 100000; $i++) {
$data[] = [
'body' => $faker->text,
'image' => $faker->imageUrl(),
'user_id' => $users->random(),
'created_at' => now()->toDateTimeString(),
'updated_at' => now()->toDateTimeString(),
];
}
$chunks = array_chunk($data, 10000);
foreach ($chunks as $chunk) {
Post::insert($chunk);
}
}
}

laravel seeder is giving an error and won't seed

I've been trying to get my seeder to work but it keeps giving me the following error
Call to undefined function Database\Seeders\factory()
at database/seeders/ContactTableSeeder.php:16
12▕ * #return void
13▕ */
14▕ public function run()
15▕ {
➜ 16▕ factory('App\Models\Contact', 100)->create()
17▕ ->each(function($contact) {
18▕ $contact->addresses()->save(
19▕ (factory(App\Address::class)->make())
20▕ );
+24 vendor frames
25 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
My DatabaseSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
//Model::unguard(); // Disable mass assignment
$this->call(ContactTableSeeder::class);
//Model::reguard();
}
}
My ContactTableSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class ContactTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory('App\Models\Contact', 100)->create()
->each(function($contact) {
$contact->addresses()->save(
(factory(App\Address::class)->make())
);
});
}
}
My ContactFactory
<?php
/* #var $factory \Illuminate\Database\Eloquent\Factory */
use App\Models\Contact;
use Faker\Generator as Faker;
$factory->define(Contact::class, function (Faker $faker) {
return [
'firstName' => $faker->firstName,
'lastName' => $faker->lastName,
'email' => $faker->unique()->email,
'phone' => $faker->phoneNumber,
'birthday' => $faker->date($format = 'Y-m-d', $max = 'now')
];
});
My AddressFactory
<?php
/* #var $factory \Illuminate\Database\Eloquent\Factory */
use App\Models\Address;
use Faker\Generator as Faker;
$factory->define(Address::class, function (Faker $faker) {
return [
'number' => $faker->number,
'street' => $faker->streetName,
'city' => $faker->city,
'state' => $faker->state,
'zip' => $faker->postcode,
'type' => 'home',
'contact_id'=> factory(App\Models\Contact::class),
];
});
Contact Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use HasFactory;
protected $fillable = [ 'firstName', 'lastName', 'email', 'phone', 'birthday' ];
public function addresses()
{
return $this->hasMany('App\Models\Address');
}
}
My Address Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
use HasFactory;
protected $fillable = [ 'id', 'number', 'street', 'city', 'state', 'zip', 'type', 'contact_id' ];
public function contacts()
{
return $this->belongsTo('App\Models\Contact');
}
}
I have tried running
composer dump-auto
composer update
None of those normal fixes seem to work.
I really have no idea why its failing
Thanks in advance for your help
In Laravel8, you need to update your factory files like below or add laravel/legacy-factories package to your project. Further info: https://laravel.com/docs/8.x/upgrade#model-factories
<?php
namespace Database\Factories;
use App\Models\Contact;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Contact::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'firstName' => $this->faker->firstName,
'lastName' => $this->faker->lastName,
'email' => $this->faker->unique()->email,
'phone' => $this->faker->phoneNumber,
'birthday' => $this->faker->date($format = 'Y-m-d', $max = 'now')
];
}
}
In seeders use factory like that:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class ContactTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
App\Models\Contact::factory()->create(100)
->each(function($contact) {
$contact->addresses()->save(
App\Address::factory()->make()
);
});
}
}
Replace your factory function factory('App\Models\Contact', 100)->create()
with this code:
\App\Models\Contact::factory()->count(100)
->create();
Why? Because In laravel 8 the default route namespace was removed
In laravel 8 the default route namespace was removed.
Try to change
factory(App\Models\Contact::class,100)->create();
To
\App\Models\Contact::factory()->create();
\App\Models\Contact::factory(100)->create(); \\If you want to create 100 number of record then

Faker laravel unknown formatter image

Am using faker in laravel and in my seeder i have
public function run()
{
$faker = new Faker\Generator();
//create a user
$adminuser = App\User::create(
[
'name' => 'admin',
'first_name' => 'firstuser',
'profile_pic'=>$faker->image('storage/app/public/users',400,300, 'people', false),
]
);
But now am getting an error
Unknown formatter "image"
Where am i going wrong
I just want to add an image to a user generated via faker
From the docs on basic usage
public function run()
{
// instead of using new Faker\Generator()
$faker = Faker\Factory::create();
//create a user
$adminuser = App\User::create(
[
'name' => 'admin',
'first_name' => 'firstuser',
'profile_pic' => $faker->image('storage/app/public/users',400,300, 'people', false),
]
);
}
You must use the ‍‍Method Injection
for example :
<?php
use Illuminate\Database\Seeder;
use Faker\Generator as Faker;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #param Faker $faker
* #return void
*/
public function run(Faker $faker)
{
$adminuser = App\User::create(
[
'name' => $faker->name,
'first_name' => $faker->firstName,
'profile_pic' => $faker->image(public_path('img'),400,300, 'people', true),
]
);
}
}

lumen generate fake data with faker from given array

I want to generate fake data for user with diffrent role ,
My file is below,
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Faker\Factory as Faker;
class InsertUserSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run() {
$faker = Faker::create();
foreach (range(1, 10) as $index) {
DB::table('user')->insert([
'name' => $faker->name,
'email' => $faker->email,
'role' => 'admin',
]);
}
}
}
From above code it will generate 10 records of admin role.
I want to generate records with different role from['admin','superadmin','client','agent','engineer']
how can I fetch value for role from given array of roles.
You can use the method randomElement($array) of the faker to do the job like so:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Faker\Factory as Faker;
class InsertUserSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run() {
$faker = Faker::create();
foreach (range(1, 10) as $index) {
DB::table('user')->insert([
'name' => $faker->name,
'email' => $faker->email,
'role' => $faker->randomElement([
'admin',
'superadmin',
'client',
'agent',
'engineer',
]),
]);
}
}
}
For reusability, I would suggest using model factories instead of creating the models directly in the seeder. You can read up on it in the documentation.

Categories