I'm trying to seed my DB but I have a problem when I use modelName::create() or $modelName->save().
I have this kind of error
{"error":{"type":"Symfony\Component\Debug\Exception\FatalErrorException","message":"Call to undefined method Doc::save()","file":"/Applications/MAMP/htdocs/Doc_project/app/database/seeds/DatabaseSeeder.php","line":45}
or
Call to undefined method Doc::create()
but i dont know why.
My Model :
class Doc extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'doc';
protected $fillable = array('creators_name', 'type_document', 'title', 'description');
public function steps(){
return this->hasMany('Step')
}
public function tags(){
return this->belongsToMany('Tag', 'doc_tag', 'id_doc', 'id_tag')
}
}
My Seeder :
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Eloquent::unguard();
$this->call('DocAppSeeder');
$this->command->info('Doc app seeds finished.'); // show information in the command lin }
}
}
class DocAppSeeder extends Seeder {
public function run(){
DB::table('doc')->delete();
DB::table('step')->delete();
DB::table('tag')->delete();
DB::table('doc_tag')->delete();
/* DB::table('doc')->insert(array(
'creators_name' => 'Alexis',
'type_document' => 'Solution',
'title' => 'NoAD Printer',
'description' => 'Installation imprimante en NoAd'
));*/
$doc = new Doc;
$doc->creators_name = 'Alexis';
$doc->type_document = 'Solution';
$doc->title = 'NoAD Printer';
$doc->description = 'Installation imprimante en NoAd';
$doc->save();
/*$docTest = Doc::create(array(
'creators_name' => 'Alexis',
'type_document' => 'Solution',
'title' => 'NoAD Printer',
'description' => 'Installation imprimante en NoAd'
));
}
}
I try with DB::Table(...)->insert(...)it works, but I can't use it because I need to get some information on each object
Someone have an idea?
Thank you
It looks like PHP is using a different global level Doc class than the one you think it is. Maybe for a facade or alias (self link, contains details instructions on how to debug facade issues)?
Regardless, the best course of action is to see where PHP thinks this class is. In you seeder, right before save, include the following debugging code
$r = new ReflectionClass('Doc');
var_dump(
$r->getFilename()
);
var_dump(
$r->getName()
);
This will tell you the full-name of the class (if it's an alias) and where the class is defined. My guess is the class you think is Doc is not your Eloquent model, and is, in fact, a different class.
Based on your comments below, it sounds like someone's defined a class named Doc in
/Applications/MAMP/htdocs/Doc_project/app/database/migrations/2014_10_12_201016_doc.php
This isn't normal -- although it's easy to see how it might have happened. You probably used the artisan command to create a migration like this
php artisan migrate:make doc
By not using the more explicate form
php artisan migrate:make create_doc_table
You inadvertently create a migration class with the same name as your model. Try recreating this migration with a less specific name, and you should be all set.
Check your migration file -
Rollback the migration, create a fresh version of migration file and proceed.
It usually happens with artisans when used to create a migration.
For me, i rollback the migration and recrested the migration with another name and it works.
Related
I'm a newcomer to Laravel, and I got errors when I tried to generate some info in the table in the database using a factory.
Call to a member function count() on null " at
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/HasFactory.php:17.
Maybe somebody had the same problem? I will be grateful if someone can help. Below will be the code of certain elements:
Seeder
class UsersTableSeeder extends Seeder
{
public function run()
{
Users::factory()->count(30)->create();
}
}
Factory
class UploadInfoFactory extends Factory
{
protected $model = Users::class;
public function definition()
{
return [
'Name' => $this->faker->name,
'Birthday' => $this->faker->date('d-m-Y'),
'Phone number' => $this->faker->phoneNumber,
'Phone balance' => $this->faker->numberBetween(-50,150),
];
}
}
DatabaseSeeder
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(UsersTableSeeder::class);
}
}
Migration
class CreateInfoUsers extends Migration
{
public function up()
{
Schema::create('info_users', function (Blueprint $table) {
$table->integerIncrements('id');
$table->string('name',100);
$table->date('Birthday');
$table->string('Phone number',100);
$table->string('Phone balance',100);
});
}
}
The error code that pops up in bash when we enter php artisan db: seed:
Call to a member function count() on null at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/HasFactory.php:17
13▕ public static function factory(...$parameters): Factory {
14▕ $factory = static::newFactory() ?: Factory::factoryForModel(get_called_class());
15▕
16▕ return $factory
➜ 17▕ ->count(is_numeric($parameters[0] ?? null) ? $parameters[0] : null)
18▕ ->state(is_array($parameters[0] ?? null) ? $parameters[0] : ($parameters[1] ?? []));
19▕ }
20▕
21▕ /**
This might help someone else cause my problem was different. When seeding the database, Laravel printed out the same error that #Yurii experienced.
Seeding: Database\Seeders\ProfileSeeder
Error
Call to a member function count() on null
at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/HasFactory.php:18
Indeed my artisan console failed to create the Factory for my Profile model
$ php artisan tinker
>>> use Illuminate\Database\Eloquent\Factories\Factory;
>>> Factory::factoryForModel(Profile::class);
=> null
After some minutes of investigation, I found out that I forgot to return the Factory in the configure method
class ProfileFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Profile::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
// some stuff
];
}
public function configure()
{
// it miss the return here !!
$this->afterCreating(function (Profile $profile) {
// do stuff with $profile
});
}
}
So, when the Factory was instantiated, the configure method was called but no Factory was returned! Placing the return fixed the issue.
If you want a model to automatically use a factory you would have to name the factory in a particular way, otherwise you would have to define a way to resolve the particular factory you want to use for the model.
Rename your factory to UsersFactory and it will automatically be used be the Users model.
Though, I suggest renaming Users to User as the convention is for models to be in the singular and tables to be in the plural. If you change the model name you would then need to change the factory to UserFactory to match.
"The HasFactory trait's factory method will use conventions to determine the proper factory for the model. Specifically, the method will look for a factory in the Database\Factories namespace that has a class name matching the model name and is suffixed with Factory. If these conventions do not apply to your particular application or factory, you may overwrite the newFactory method on your model to return an instance of the model's corresponding factory directly"
Laravel 8.x Docs - Database Testing - Creating Models Using Factories - Connecting Factories and Models
I am following this tutorial until I need to generate seeds using: php artisan db:seed. It always said that my Article and User class are not found.
I have looking for solution like in:
https://laracasts.com/discuss/channels/lumen/unable-to-run-php-artisan-dbseed-due-to-missing-class (setting up composer.json's auto load paths and composer dump-autoload)
Laravel cannot find class of a package
I have deleting my vendor folder and do composer install again
Also importing the file manually, require_once with relative path to the model from the seeding or root of the projet, but neither works.
I think this should work out-of-the-box but it isn't. What is my problem? And what is my solution?
EDIT 1: Someone requested seeders codes here you are!
Article Seeder
<?php
use Illuminate\Database\Seeder;
class ArticlesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// Let's truncate our existing records to start from scratch.
Article::truncate();
$faker = \Faker\Factory::create();
// And now, let us create a few articles in our database:
for ($i = 0; $i < 50; $i ++) {
Article::create([
'title' => $faker->sentence,
'body' => $faker->paragraph,
]);
}
}
}
User Seeder
<?php
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// Let's clear the user table first
User::truncate();
$faker = \Faker\Factory::create();
// Let's make sure everyone has the same password and
// let's hash it before the loop, or else our seeder
// will be too slow.
$password = Hash::make('toptal');
User::create([
'name' => 'Administrator',
'email' => 'admin#test.com',
'password' => $password,
]);
// And now let's generate a few dozen users for our app:
for ($i = 0; $i < 10; $i ++) {
User:;create([
'name' => $faker->name,
'email' => $faker->email,
'password' => $password,
]);
}
}
}
Database Seeder
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$this->call(UsersTableSeeder::class);
$this->call(ArticlesTableSeeder::class);
}
}
First you should import the full class path, i.e.- App\User. Then regenerate the autoload file with- composer dump-autoload
You should either import the models that you've use so you can use just the Model's class name in your code or use the fully qualified name of the Model.
E.g., instead of just User, use App\User.
Use imports if you think you will have many instance where you will use the User class name, to avoid the hassle of typing the fully qualified name.
<?php
...
use App\User;
...
$users = User::all(); // <-- now you can do this.
I followed the same tutorial. Just add a line "use App\Article;" so that your class will find the appropriate class.
Its like including a header file path in c/c++.
I have been around this problem for so long and cannot solve it... I found several people with (apparently) the same problem as me, but any of the answers helped me.
I have the following "Sector.php" inside "app" folder:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Sector extends Model
{
protected $table = 'sectors';
protected $fillable = ['name'];
protected $guarded = ['id'];
public function services()
{
return $this->belongsToMany('App\Service', 'services_sectors', 'sector_id', 'service_id');
}
public function observations()
{
return $this->belongsToMany('App\Observation', 'observations_sectors', 'sector_id', 'observation_id');
}
}
And the following "DatabaseSeeder.php" inside "database/seeds":
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
DB::table('sectors')->delete();
Sector::create(['name' => 'Health']);
$this->command->info('Sectors table seeded');
}
}
So, when I access my server I run the command php artisan db:seed but I have the following error:
[Symfony\Component\Debug\Exception\FatalThrowableError]
Class 'Sector' not found
I have been trying ./composer update, ./composer dump-autoload -o, changing Sector to App\Sector in the seeder file but the error just changes to Class 'App\Sector' not found.
If I add use App\Sector; to the top of the Seeder file the error is the same.
It seems I tried all the solutions that are online, so maybe I have some configuration done incorrectly? Any suggestions on this?
Try adding use App\Sector; to your seeding file.
Once you have it working, think about separating your seeding files into their separate classes. It is much easier to maintain that way.
Generate Seeder File
First, in terminal, generate a new seed file:
php artisan make:seeder SectorsTableSeeder
Transfer your seeding code into the run method of this new file.
Call seeder files
Then, modify the DatabaseSeeder.php file to run the SectorsTableSeeder class. For example:
public function run()
{
$this->call(SectorsTableSeeder::class);
}
Update
Sorry, I missed that part.
This is what I would try:
$now = date('Y-m-d H:i:s');
public function run()
{
DB::table('sectors')->delete();
DB::table('sectors')->insert([
'name' => 'Health',
'created_at' => $now,
'updated_at' => $now,
]);
$this->command->info('Sectors table seeded');
}
Im trying to create a seeder table that fills a table with some dummy data using the laravel ModelFactory. I keep getting this error and I'm out of ideas on fixing it.
The 'Race' Model
<?php
namespace App\Game;
use Illuminate\Database\Eloquent\Model;
class Race extends Model
{
//
public $timestamps = false;
protected $fillable = ['name','description','icon'];
}
File 2 The Model Factory File
$factory->define(App\Game\Race::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'description' => $faker->text,
'icon' => $faker->url,
];
});
File 3 The Seeder File
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class RacesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
//
factory(App\Game\Race::class, 10)->create()->each(function($u) {
$u->posts()->save(factory(App\Game\Race::class)->make());
});
}
}
I am getting the following error
Call to undefined method Illuminate\Database\Query\Builder::posts()
This happens when I call 'php artisan db:seed'
It looks like you copied the seeder directly from the documentation. In the documentation's example, there is a User model that is related to a Posts model via a function posts that is defined within the user model. See this documentation page for more information about why there's a posts method on the User model.
You have a Race model that does not have Posts related to it, indicated by the absence of posts method inside your race model. Try simplifying the factory to this:
public function run()
{
//
factory(App\Game\Race::class, 10)->create();
}
This should create 10 race entries in your database for you. You would want to provide the closure passed to the each method only if you intend to also create other models within the seeder that are related to each instance the factory creates, or do some other action for every instance (each) of a Race that gets created by the factory.
Been looking all over the internet but don't seem to find an answer to my problem. I've been diving into testing controllers in Laravel using PHPUnit and Mockery. However, I don't seem to get my Eloquent based models mocked correctly. I did manage to mock my Auth::user() the same way, although this is not used in the test below.
Function in AddressController that needs to be tested:
public function edit($id)
{
$user = Auth::user();
$company = Company::where('kvk', $user->kvk)->first();
$address = Address::whereId($id)->first();
if(is_null($address)) {
return abort(404);
}
return view('pages.address.update')
->with(compact('address'));
}
ControllerTest containing setUp and mock method
abstract class ControllerTest extends TestCase
{
/**
* #var \App\Http\Controllers\Controller
*/
protected $_controller;
public function setUp(){
parent::setUp();
$this->createApplication();
}
public function tearDown()
{
parent::tearDown();
Mockery::close();
}
protected function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
}
AddressControllerTest extending ControllerTest
class AddressControllerTest extends ControllerTest
{
/**
* #var \App\Models\Address
*/
private $_address;
/**
* #var \App\Http\Controllers\AddressController
*/
protected $_controller;
public function setUp(){
parent::setUp();
$this->_controller = new AddressController();
$this->_address = factory(Address::class)->make();
}
public function testEdit404(){
$companyMock = $this->mock(Company::class);
$companyMock
->shouldReceive('where')
->with('kvk', Mockery::any())
->once();
->andReturn(factory(Company::class)->make([
'address_id' => $this->_address->id
]));
$addressMock = $this->mock(Address::class);
$addressMock
->shouldReceive('whereId')
->with($this->_address->id)
->once();
->andReturn(null);
//First try to go to route with non existing address
$this->action('GET', 'AddressController#edit', ['id' => $this->_address->id]);
$this->assertResponseStatus(404);
}
}
The error it keeps throwing is:
1) AddressControllerTest::testEdit404
Mockery\Exception\InvalidCountException: Method where("kvk", object(Mockery\Matcher\Any)) from Mockery_1_Genta_Models_Company should be called exactly 1 times but called 0 times.
Perhaps anyone has an idea?
Okay, after finding multiple posts by Jeffrey Way (the guy behind Laracasts) recommending people to stop mocking Eloquent objects and instead use in memory databases I've tried that approach. I thought this would perhaps be very usable for other users having the same problems in the future, so I'll explain below.
Right now I've edited the my 'config/database.php' file to support in-memory database option using sqlite:
'sqlite' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
Next on top of the file you'll see the following configuration:
'default' => env('DB_CONNECTION', 'mysql'),
This can stay the same, it means that Laravel will check your .env variables to find a 'DB_CONNECTION' or else use mysql as default. This is probably what you'd like to do when running your application as usual. However with testing you would like to override this configuration and set the database config to 'sqlite' temporarily. This can be done by adding the 'DB_CONNECTION' variable to your .env file:
DB_CONNECTION=mysql
Finally in your phpunit.xml, the configuration file used by Laravel to instantiatie the unit tests, you have to tell that when testing this variable should be set to 'sqlite':
<env name="DB_CONNECTION" value="sqlite"/>
Now you are done and Laravel will start up an invisible in-memory database everytime you are about to go testing. Don't forget to add the following line to tests that need the database.
use \Illuminate\Foundation\Testing\DatabaseMigrations;
It will tell Laravel run your database migrations before starting the tests, so you can use the tables like you normally would.
This way it works perfectly for me! Hope you guys can use it.