How to fix Call to undefined method App\Models\TableName::factory? - php

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

Laravel saving polymorphic model doesn't have a default value

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

What causes the 'Unknown format "factory"' error in this Laravel 8 app?

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(),
];
}
}

How to pass arguments from seeders to factories?

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.

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

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