Symfony\Component\Debug\Exception\FatalThrowableError - laravel-5

i'm trying to seed data to database using laravel.
this is my factory model
$factory->define(App\product::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'description' => $faker->description,
'price' =>$faker->price,
'image' => $faker->image,
'value' => $faker->value,
'category_id' => $faker->category_id,
'is_voucher' => $faker->is_voucher,
'voucher_id' => $faker->voucher_id,
];
});
in the producttableseed
public function run()
{
$product = factory(product::class, 10)->create();}
and when i run php artisan db:seed
i get this error
Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to Illuminate\Database\Eloquent\Factory::{closure}() must be an instance of Faker\Generator\Generator, instance of Faker\Generator given

Do you have the line
use Faker\Generator as Faker;
before you define your factory? This, plus changing first line to this
$factory->define(App\product::class, function (Faker $faker) {
works for me.
Also, be careful with
$product = factory(product::class, 10)->create();}
You are seeding 10 database entries here. Your variable name being singular, looks like you might be up for a surprise when you try working with an array that has multiple entries.

Related

Laravel factory cannot create because already has one

I want to create with factory in the test case but i got a validation error it say The name has already been taken. But how? It always refresh database every time the test start run.
The factory
$factory->define(Companies::class, function (Faker $faker) {
return [
'name' => $faker->unique()->company,
'email' => $faker->email,
'website' => $faker->url,
];
});
The test
Storage::fake('local');
$image = UploadedFile::fake()->image('avatar.jpg', 150, 150);
$companies = factory(Companies::class)->create([
'logo' => $image
]);
$company = $companies->toArray();
$this->actingAs($this->user);
$response = $this->postJson('/home/companies/create/add', $company);
$response->assertStatus(302);
i suggest to use the trait RefreshDatabase in your test then you reset the database after each test to avoid side effect.
just on the top of your test class write :
use RefreshDatabase;
Good luck

How to convert object return by laravel model factory create method into array containing model fields?

For example, I have a UserFactory.php
<?php
use App\User;
use Faker\Generator as Faker;
use Illuminate\Support\Str;
$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'role' => 'USER',
'password' => 'sasdcsdf34', // password
'remember_token' => Str::random(10),
];
});
Now, I can create a user as following
$user = factory(User::class)->create();
Now, How can I convert this $user object into array containing user info like name,email etc without initializing new array and manually assigning every $user object property. ??
I DON'T want to manually assign like following as it is tedious if there are many properties in $user object
$userArray=[
'id' => $user->id,
'name' => $user->name,
'email' => $user->email
]
I have tried this but it creates array containing various other properties and actual values needed are nested inside properties
$userArray=array($user)
You should try using the raw method of factory instead of create.
$user = factory(User::class)->raw();
This should give you an array you can work with.
Try to add something like this to your model class:
public function getArr(){
foreach($this->attributes as $key => $val){
$array[$key] = $val;
}
return $array;
}
If you wish to have this function in every model you could create trait with this function and then just attach it in model class or any class extending it.
You can use json_decode.
// Laravel 7
$userArray = json_decode(factory(User::class)->create(), true);
// Laravel 8
$userArray = json_decode(User::factory()->create(), true);
For Laravel 8, instead of make or create method, use:
User::factory()->raw();
This will return an array

How in feature testing use data from factory?

In laravel 5.8 app with tests I make posting data with some dummy data, like:
$newVoteCategoryRow= [
'id' => null,
'name' => $new_vote_category_row_name,
'meta_description' => 'vote category meta_description on ' . now(),
'meta_keywords' => [ 'vote category meta_description on ' . now(), 'meta_keywords' ],
'active' => true,
'in_subscriptions' => true,
];
$response = $this->actingAs($loggedUser)->post('/admin/vote-categories', $newVoteCategoryRow);
$this->assertCount( $vote_categories_count+1, VoteCategory::all() );
it works ok, but actually I have factory for VoteCategory table in /database/factories/VoteCategoryFactory.php, defined :
<?php
use Faker\Generator as Faker;
use \Cviebrock\EloquentSluggable\Services\SlugService;
use App\VoteCategory;
$factory->define(App\VoteCategory::class, function (Faker $faker) {
$name= 'Vote category ' . $faker->word;
$slug = SlugService::createSlug(VoteCategory::class, 'slug', $name);
return [
'name' => $name,
'slug' => $slug,
'active' => true,
'in_subscriptions' => false,
'meta_description' => $faker->text,
'meta_keywords' => $faker->words(4),
];
});
and my question is if there is a way in post request instead of $newVoteCategoryRow array use my factory, not adding row in database but
reading data from factory for post request ?
to achieve that you just need to use your factory within the test case method:
to create VoteCategory u have to methods, the first one is make and this one will create an instance of VoteCategory without persisting it within the database, and the create method will persist the new VoteCategory within the database.
in your case, you want to create a new instance without adding it to the database, for that you just need to use make:
$newVoteCategoryRow = factory('App\VoteCategory')->make(); // add this line to your test case method.
$response = $this->actingAs($loggedUser)->post('/admin/vote-categories', $newVoteCategoryRow->toArray());
$this->assertCount( $vote_categories_count+1, VoteCategory::all());
for more information, you can check the doc Laravel 5.8: using-factories

Creating Seeder with foreign key field Laravel 5.3

I'm trying to create a seeder for my table addresses but one field of my table, is a foreign key, This Fk references a user id of my table users.
My Seeder Class:
class AddressesSeeder extends Seeder
{
public function run()
{
$faker = Faker::create();
// following line retrieve all the user_ids from DB
$users = User::all()->pluck('id');
foreach(range(1,50) as $index){
$address = Address::create([
'user_id' => $faker->randomElement($users),
'street' => $faker->street,
'number' => $faker->number,
'city' => $faker->city,
'state' => $faker->state,
'created_at' => $faker->datetime,
'updated_at' => $faker->datetime,
]);
}
}
}
When i run the db:seed, i receave the error:
[ErrorException]
Argument 1 passed to Faker\Provider\Base::randomElements() must be of the type array, object given, called in C:\xampp\htdocs\projeto\vendor\fzaninotto\fake
r\src\Faker\Provider\Base.php on line 205 and defined
It's because pluck() will return an object, use toArray() to parse it.
$users = User::all()->pluck('id')->toArray();

How to seed timestamps on laravel 4.1?

Good day,
I was having an error "Object of class DateTime could not be converted to string" when Im trying to seed my database.
here is my migration code:
public function up()
{
Schema::create('tblinventory', function(Blueprint $table) {
$table->increments('id');
$table->integer('itemId');
$table->enum('status', array('active','inactive'))->default(null)->nullable();
$table->float('purchasePrice');
$table->float('sellingPrice');
$table->date('expirationDate');
$table->float('ReceivedQuantity');
$table->float('soldQuantity');
$table->timestamps();
});
}
and my seeder:
<?php
class InventoryTableSeeder extends Seeder {
public function run()
{
// Uncomment the below to wipe the table clean before populating
DB::table('tblinventory')->truncate();
$insert = [
[
'itemId' => '1',
'status' => 'inactive',
'ReceivedQuantity'=>'100',
'SoldQuantity'=>'93',
'sellingPrice'=>'4.5',
'purchasePrice'=>'3.5',
'created_at' => new DateTime,
'expirationDate'=>date('2015-02-22')
],
[
'itemId' => '1',
'status' => 'inactive',
'ReceivedQuantity'=>'300',
'SoldQuantity'=>'300',
'sellingPrice'=>'4.75',
'purchasePrice'=>'3.65',
'expirationDate'=>date('2015-02-22')
],
[
'itemId' => '2',
'status' => 'inactive',
'ReceivedQuantity'=>'100',
'SoldQuantity'=>'93',
'sellingPrice'=>'3.5',
'purchasePrice'=>'2.5',
'expirationDate'=>date('2014-07-22')
],
[
'itemId' => '3',
'status' => 'inactive',
'ReceivedQuantity'=>'100',
'SoldQuantity'=>'93',
'sellingPrice'=>'12.5',
'purchasePrice'=>'10.5',
'expirationDate'=>date('2017-01-02')
],
[
'itemId' => '3',
'status' => 'inactive',
'ReceivedQuantity'=>'100',
'SoldQuantity'=>'100',
'sellingPrice'=>'14.5',
'purchasePrice'=>'13.5',
'expirationDate'=>date('2017-07-22')
],
[
'itemId' => '4',
'status' => 'inactive',
'ReceivedQuantity'=>'100',
'SoldQuantity'=>'93',
'sellingPrice'=>'24.5',
'purchasePrice'=>'23.5',
'expirationDate'=>date('2015-07-22')
]
];
DB::table('tblinventory')->insert($insert);
// Uncomment the below to run the seeder
// DB::table('inventories')->insert($inventories);
}
}
I get the error when I put 'created_at'=> new DateTime. How can I fix this? thank you!
Try to create your dates using Carbon (Laravel uses it internally):
'expirationDate' => \Carbon\Carbon::createFromDate(2014,07,22)->toDateTimeString()
or
'created_at' => \Carbon\Carbon::now()->toDateTimeString()
I would recommend using PHP Faker if you want to randomize your seeds for mock data. Otherwise you can just use
date('Y-m-d H:i:s');
Using Faker
https://github.com/fzaninotto/Faker
Add to composer.json
"fzaninotto/faker" : "dev-master",
Include the Namespace
use Faker\Factory as Faker;
Initialize Faker
$faker = Faker::create();
Start Faking Stuff
$faker->dateTime();
I am a little late to the party here but I wanted to give another option that others may find useful.
If you have already created your models using Eloquent, then there is another option to have Eloquent fill those fields for you automatically by using the orm. Assuming your btlinventory has a model name of Inventory:
foreach($insert as $row ){
$inventory = new Inventory;
$inventory->fill($row);
$inventory->save();
}
insert is a query builder method so by itself it will not handle any Eloquent tasks, however, you can always chain query builder methods off of an Eloquent object and then it would work. If you use Inventory::create($array); and still have issues then I hear this may get fixed by explicitly stating public $timestamps = true; in your model.

Resources