Suppose I have a user factory to create user, for specific user I want to add more information, for this I've defined state inside factory, but if I use state, then I can not call related method of user after user creation suppose I should assign role to the user using assignRole($role).
Following is my UserFactory.php
$factory->define(User::class, function (Faker $faker) {
return [
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'first_name' => $faker->name,
'last_name' => $faker->lastName,
'phone' => $faker->phoneNumber,
'password' => bcrypt('12345678'),
];
});
$factory->state(User::class, 'Admin', function (Faker $faker) {
$country = factory(Country::class)->create();
$province = factory(Province::class)->create();
static $afghanistanId = 1;
$admin= [
'about' => $faker->sentence($nbWords = 20, $variableNbWords = true),
'address' => $faker->address,
];
if($country->id == $afghanistanId) {
$admin['province_id'] = $province->id;
} else {
$admin['city'] = $faker->city;
}
return $admin;
});
Now if I use this factory like bellow:
$user = factory(User::class, $count)->state('Admin')->create();
$user->assignRole('Admin');
Following shows this error:
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::assignRole does not exist
By passing $count to the factory method $user = factory(User::class, $count)...->create(); you're creating multiple users and the return is a Collection like your Error says.
To assigne the 'Admin' role to each user you have to iterate them
$users = factory(User::class, $count)->state('Admin')->create();
foreach($users as $user)
$user->assignRole('Admin');
Related
I have a list of names $names = ['Adam','Beth,'Chancie','Dale', 'Edward']; etc.. That I want to use in a Laravel factory, or seeder, I don't know which one.
Basically, I still want to use the Faker functionality for everything else, but provide my own custom list of names in the order they are listed in the array.
$factory->define(User::class, function (Faker $faker) {
return [
'name' => MY_CUSTOM_LIST_NAME,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
});
You could always create a private method which you call as you loop over each name in your array.
$factory->define(User::class, function (Faker $faker) {
foreach($name in $names) {
$this->customFakerMethod($name);
// your logic here ...
}
});
This function just takes the name as a parameter.
private function customFakerMethod($name)
{
return [
'name' => $name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
So your users will be created in the order that you wish.
I'm using laravel factories to generate some fake users in my database but I don't know how to get the user id of the user that I'm currently generating.
I want to get the id of the current user so I can hash it and put it in the slug.
This is my code so far:
$factory->define(User::class, function (Faker $faker) {
$name = $faker->name;
$email = $faker->unique()->safeEmail;
$date_of_birth = $faker->date();
return [
'name' => $name,
'email' => $email,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'date_of_birth' => $date_of_birth,
'slug' => (\App\User::class)->id //This is the part that doesn't work,
];
});
Another way to approach it would be to set the slug outside of the factory.
This would mean that slug would need to be nullable though.
Migration:
$table->string('slug')->nullable();
Factory:
$factory->define(User::class, function (Faker $faker) {
$user = [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
return $user;
});
Seeder:
$users = factory(User::class, 5)->create();
foreach($users as $user) {
$user->slug = $user->id;
$user->save();
}
UPDATE:
Laravel offers Factory Callbacks (See Docs)
So, you don't need to loop through in your seeder, just chain the afterCreating() method:
$factory->define(App\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
})->afterCreating(\App\User::class, function (\App\User $user, Faker $faker) {
$user->slug = $user->id;
$user->save();
});
If your users.id is auto increment, you can get the same ID if you use the answer of the question I gave in comment, by using static variable and increment it.
$factory->define(App\AliasCommand::class, function (Faker\Generator $faker) {
$name = $faker->name;
$email = $faker->unique()->safeEmail;
$date_of_birth = $faker->date();
static $id = 1;
return [
'name' => $name,
'email' => $email,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'date_of_birth' => $date_of_birth,
'slug' => $id++,
];
});
Not tested, but this is how I did it a while ago.
ID is only assigned after the record is inserted into the database. So there is no way to access it in your factory.
Assuming you need the slug not only as part of your testing/seeding, the best way is to hook into the model's created event:
class User extends Authenticatable
{
protected static function boot() {
parent::boot();
static::created(function ($user) {
$user->update(['slug' => $user->id]);
});
}
}
I want to fill my database with fake data but when I run seed command it keeps giving me Array To String Conversion Exception I know Its because some function but i can not detect which one?
I tried using $faker->word property instead of name but same problem
$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'verified' => $verified = $faker->randomElements([User::VERIFIED_USER, User::UNVERIFIED_USER]),
'verification_token' => $verified == User::VERIFIED_USER ? null : User::generateVerficationCode(),
'admin' => $faker->randomElements([User::REGULAR_USER, User::ADMIN_USER]),
'email_verified_at' => now(),
'password' =>
'$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(1, 10),
];
});
$factory->define(Category::class, function(Faker $faker){
return [
'name' => $faker->name,
'description' => $faker->paragraph,
];
});
and Here is my Database Seeder class function
public function run()
{
DB::statement('set FOREIGN_KEY_CHECKS = 0');
User::truncate();
Category::truncate();
Product::truncate();
Transaction::truncate();
DB::table('category_product')->truncate();
$userQuantity = 200;
$categoriesQuantity = 50;
$productsQuantity = 1000;
$transactionQuantity = 1000;
factory(User::class, $userQuantity)->create();
factory(Category::class, $categoriesQuantity)->create();
factory(Product::class, $productsQuantity)->create()->each(function($product) {
$categories = Category::all()->random(mt_rand(1, 5))->pluck('id')->all();
$product->categories()->attach($categories);
});
factory(Transaction::class, $transactionQuantity)->create();
}
The issue is that $faker->randomElements() is giving you an array. What you want is $faker->randomElement() that will pick just one element from the array you provide.
what i need is to save some data besides creating the user, here is what I've been trying to do in my RegisterController.php :
protected function create(array $data)
{
if (isset($data['checkbox'])) {
$type = 1;
$available = 1;
} else {
$type = 0;
$available = 0;
}
$user = User::create([
'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'type' => $type,
'available' => $available,
'company' => $data['company'],
'job' => $data['job'],
]);
$user->profilesInfoModel()->create([
'bio' => $data['bio'],
'site' => $data['site'],
'location' => $data['location'],
'education' => $data['education'],
]);
return $user->with('profilesInfoModel');
}
The User.php (Model) has a one to one relationship with profilesInfoModel (yes, i know i should change the name of the model to make it more comfortable).
But after trying to register a user... i get this error message: Method Illuminate\Database\Query\Builder::profilesInfoModel does not exist.
What is actually going on?
The relationship should be like this
User Model
public function profile()
{
return $this->hasOne(ProfileInfo::class, 'user_id');
}
Assuming you have ProfileInfo as Profile model and it has user_id as foreign key references users table id field
Now you can create profile from $user like this
$user->profile()->create([
'bio' => $data['bio'],
'site' => $data['site'],
'location' => $data['location'],
'education' => $data['education'],
]);
$user->load('profile'); //lazy eager load
return $user;
1.in App\Model\User
public function profilesInfoModel()
{
return $this->hasOne(App\Model\User);
}
2.to call
use App\Model\User
in RegisterController
$factory->define(App\Client::class, function (Faker\Generator $faker) {
static $password;
$company_name = $faker->Company;
return [
'name' => $company_name,
'short_name' => substr($company_name, 0, 3),
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
$factory->define(App\Campaign::class, function (Faker\Generator $faker) {
static $password;
return [
'unique_id' => $faker->numerify('ABC###'),
'client' => function() {
return factory('App\Client')->create()->id;
}
];
});
I am generating come clients and campaigns. One client can have many campaigns
How do I take the short_name from the Company and pass it to a the campaign class so I can append it to a random string to create a unique id in the client?
You're almost there. You don't need to use an anonymous function in the campaign class, you can just reference the factory directly. Use a variable inside the Campaign factory and just reference whatever values you need.
$factory->define(App\Campaign::class, function (Faker\Generator $faker) {
$client = factory(App\Client::class)->create();
return [
'unique_id' => $faker->numerify('ABC###') . $client->short_name,
'client' => $client->id
];
});