I have created a seeder that populates data in Laravel but was having a BadMethodCallException Call to undefined method App\Models\Project::factory(). Why is this happening? Below is my seeder code.
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\{
Project, User
};
class ProjectSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Project::factory()->count(10)->create();
foreach(Project::all() as $project) {
$users = User::inRandomOrder()->take(rand(1, 3))->pluck('id');
$project->users()->attach($users);
}
}
}
First check the project factory class inside path
database/factories/ProjectFactory.php
If it not exist create it
<?php
namespace Database\Factories;
use App\Models\Project;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProjectFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Project::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
//add your custom seeder data
return [
"project_tittle" => $this->faker->catchPhrase,
"client_name" => $this->faker->name(),
"days" => rand(45, 60),
"description" => $this->faker->text,
"start_date" => $this->faker->date('Y-m-d'),
"end_date" => $this->faker->date('Y-m-d'),
"current_status" => 1,
"completion_percentage" => 0
];
}
}
If your are using different namespace on model you need to add model like this in your factoryclass
protected $model = Project::class;
I hope it works for you
I've solved it temporarily by using DB facade instead of a factory.
use Illuminate\Support\Facades\DB;
DB::table('projects')->insert([
'name' => Str::random(10),
'created_at' => now(),
'updated_at' => now(),
]);
Related
I'm working on a Laravel 9 project. I'm new to Polymorphic relationships and believe I need to define one.
In my application, I have a parent model called Application that has a single ApplicationGBPayday model, but it could have other models in the future for different products/countries.
I've defined my Application model schema to contain a modelable morph fieldset, and in my controller where I create an Application I then need to create and link the ApplicationGBPayday, but I'm getting an error right now:
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1364 Field 'modelable_type' doesn't have a default value
My controller I'm doing:
// create application
$application = Application::create([
'user_id' => $affiliate->user_id,
'company_id' => $affiliate->company_id,
'country_id' => $affiliate->affiliate_product->country->id,
'product_id' => $affiliate->affiliate_product->product->id,
'serve_method_id' => $affiliate->affiliate_product->serve_method->id,
'application_form_id' => $affiliate->affiliate_product->application_form->id,
'pingtree_group_id' => $affiliate->affiliate_product->pingtree_group->id,
'affiliate_id' => $affiliate->id,
'thread_uuid' => $threadUUID,
'status' => 'pending',
'submitted_at' => $submittedAt
]);
$payday = ApplicationGBPayday::create($request->all());
And here's my model for Application:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Casts\Json;
class Application extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'applications';
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'submitted_at' => 'datetime',
];
/**
* Get the parent modelable model.
*/
public function modelable()
{
return $this->morphTo();
}
}
And ApplicationGBPayday:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Casts\Json;
class ApplicationGBPayday extends Model
{
use HasFactory;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'application_gb_paydays';
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'buyer_list' => Json::class,
'buyer_list_pending' => Json::class,
'buyer_list_accepted' => Json::class,
'buyer_list_declined' => Json::class,
'buyer_list_invalid' => Json::class,
'buyer_list_skipped' => Json::class,
'other_data_json' => Json::class,
'response_json' => Json::class,
];
/**
* Get the model's application
*/
public function application()
{
return $this->morphOne(Application::class, 'modelable');
}
}
I'm struggling to figure out how to save the morph fields since they can't be null here, yet I need the application created first and then the payday? What am I missing?
UPDATE
I've tried:
// create application
$application = Application::create([
'user_id' => $affiliate->user_id,
'company_id' => $affiliate->company_id,
'country_id' => $affiliate->affiliate_product->country->id,
'product_id' => $affiliate->affiliate_product->product->id,
'serve_method_id' => $affiliate->affiliate_product->serve_method->id,
'application_form_id' => $affiliate->affiliate_product->application_form->id,
'pingtree_group_id' => $affiliate->affiliate_product->pingtree_group->id,
'affiliate_id' => $affiliate->id,
'thread_uuid' => $threadUUID,
'status' => 'pending',
'submitted_at' => $submittedAt
]);
$payday = new ApplicationGBPayday($request->all());
$application->modelable()->save($payday);
Which gives me:
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1364 Field 'modelable_type' doesn't have a default value (SQL: insert into applications
I am working on a Laravel 8 app with users and posts.
The objective is to create a bunch of posts (I already have users).
namespace Database\Factories;
// import Post model
use App\Models\Post;
// import User model
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 [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => $this->faker->factory(App\Models\User::class),
];
}
}
The problem
I run php artisan tinker then Post::factory()->count(100)->create() in the terminal and I get:
InvalidArgumentException with message 'Unknown format "factory"'
UPDATE
I replace my return statement with:
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
I get this in the terminal:
Class 'Database\Factories\UserFactory' not found
Questions:
Where is my mistake?
Does the fact that I get the error Class 'Database\Factories\UserFactory' not found mean that I need to
create a UserFactory factory? Because there isn't one. (I wanted
to create posts, not users).
I don't suppose there is $this->faker->factory(..).
You can do
'user_id' => App\Models\User::factory()->create()->id,
EDIT:
'user_id' => App\Models\User::factory(),
Creating a UserFactory factory and using the below return statement did the trick:
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
So, the PostFactory class looks like this:
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 [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
}
}
I want to pass arguments ['site_id' => $site->id] to SiteMessage factory:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\SiteMessage;
use App\Models\Site;
class SitesMessagesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Site::chunk(200, function ($sites) {
foreach ($sites as $site) {
SiteMessage::factory()->count(rand(2, 6))->create(['site_id' => $site->id]);
}
});
}
}
How can I get those argument in my SiteMessage factory class?
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\SiteMessage;
use App\Models\Site;
use App\Models\Integration;
class SiteMessageFactory extends Factory
{
protected $model = SiteMessage::class;
public function definition()
{
return [
**// Soliution: remove line below, it will be overridden automaticaly. \\**
'site_id' => $arguments['site_id'], // Neet to use Id that I passed from seeder.
'integration_id'=> Integration::inRandomOrder()->first()->id,
'type' => rand(0,1) ? 'EMAIL' : 'SMS',
'title' => $this->faker->text($maxNbChars = 12),
'description' => $this->faker->sentence,
'message' => $this->faker->sentence,
'enabled' => 1,
'created_at' => now(),
'updated_at' => now(),
];
}
}
At older Laravel factory version I could pass them in callback like so:
$factory->define(SiteMessage::class, function (Faker $faker, array $arguments = []) {
//
});
but don't know how to achieve it with new Class factories. Any help would be very appreciated :)
As you can see in the laravel documentation about persisting models with factories, when you type:
SiteMessage::factory()->count(rand(2, 6))->create(['site_id' => $site->id]);
The site_id attribute from SiteMessage factory will be overrided by the $site->id you are specifying.
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
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.