Laravel Seeding missing classes - php

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++.

Related

I am getting an error when i tried to seed my database

Am getting an error when i try to seed my database in laravel 5.4 using faker
use Illuminate\Database\Seeder;
use app\PostModell;
class postcarseeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// Let's truncate our existing records to start from scratch.
PostModell::truncate();
$faker = \Faker\Factory::create();
// And now, let's create a few articles in our database:
for ($i = 0; $i < 50; $i++) {
PostModell::create([
'title' => $faker->sentence,
'body' => $faker->paragraph,
]);
}
}
Above is my seeder class which am calling in my DatabaseSeeder.php with the following command $this->call(postcarseeder::class); so that i can run php artisan db:seed
The error am getting is
You should use full namespace:
App\PostModell
Or add this to the top of the seeder class:
use App\PostModell;

Laravel 5.5 Model not found in Seed class

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');
}

How can I write migrations to insert records using phinx?

I'm using phinx to handle the migration on a new project, now I need to create a new table and insert some rows to it, I have:
$tableStatus = $this->table('status');
$tableStatus->addColumn('code', 'string');
$tableStatus->addColumn('description', 'string');
$tableStatus->save();
This add the new table but I couldn't find at the documentation how to insert rows, but it seems possible:
The AbstractMigration Class All Phinx migrations extend from the
AbstractMigration class. This class provides the necessary support to
create your database migrations. Database migrations can transform
your database in many ways such as creating new tables, inserting
rows, adding indexes and modifying columns.
It is possible? How can I do it?
As igrossiter pointed out, there is a method for this, the name of the method is insert
use Phinx\Migration\AbstractMigration;
class NewStatus extends AbstractMigration
{
protected $statusId = 1234; //It'd be nice to use an entity constant instead of magic numbers, but that's up to you.
protected $statusName = 'In Progress';
/**
* Migrate Up.
*/
public function up()
{
$columns = ['id', 'name'];
$data = [[$this->statusId, $this->statusName]];
$table = $this->table('status');
$table->insert($columns, $data);
$table->saveData();
}
/**
* Migrate Down.
*/
public function down()
{
$this->execute('Delete from status where id = ' . $this->statusId);
}
}
Edit as of December 2nd, 2015
This method's signature will change in future stable versions to something like
$data = [
['id' => 1, 'name' => 'foo'],
['id' => 2, 'name' => 'bar']
];
$table = $this->table('status');
$table->insert($data);
More info here
You can do it. Read documentation for more information.
http://docs.phinx.org/en/latest/migrations.html#executing-queries
use Phinx\Migration\AbstractMigration;
class MyNewMigration extends AbstractMigration
{
/**
* Migrate Up.
*/
public function up()
{
// execute()
$count = $this->execute('insert into users(id, name) values (5, "john")');
}
/**
* Migrate Down.
*/
public function down()
{
}
}
Run this command to generate StatusMigration class:
php vendor/bin/phinx create StatusMigration
Edit that file like:
<?php
use Phinx\Migration\AbstractMigration;
class StatusMigration extends AbstractMigration
{
public function change()
{
$this->table('status')
->addColumn('code', 'string')
->addColumn('description', 'string')
->create();
}
}
You can use Phinx's database seeding mechanism to insert rows into tables. First run following command:
php vendor/bin/phinx seed:create StatusSeeder
It will generate StatusSeeder.php file in Phinx's seeds folder.
Edit StatusSeader.php like:
use Phinx\Seed\AbstractSeed;
class StatusSeeder extends AbstractSeed
{
public function run()
{
$data = [
['code' => 'c1', 'description' => 'Some description'],
['code' => 'c2', 'description' => 'Another description'],
];
$this->table('status')
->insert($data)
->save();
}
}
Now, run following commands to create table and seed data:
php vendor/bin/phinx migrate
php vendor/bin/phinx seed:run
This question has a good answer using CakePHP 3's Migrations plugin:
public function up() {
// Save records to the newly created schema
$UsersTable = TableRegistry::get('Users');
$user = $UsersTable->newEntity();
$user->name = 'Joe Bloggs';
$user->email = 'joe#example.com';
$UsersTable->save($user);
}

Laravel Call to undefined method create() and save()

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.

Laravel : Migrations & Seeding for production data

My application needs a pre registered data set to work. So i need to insert them in the database when i set up the application.
Laravel propose two mechanisms :
Database migrations : "They allow a team to modify the database schema and stay up to date on the current schema state."
Database seeding : "Laravel also includes a simple way to seed your database with test data using seed classes."
When I read this description, none of these solutions seems to be adapted.
A similar question has been asked on stackoverflow and answered. The answer proposes to use the a database seeder to populate the database by detecting the current environment :
<?php
class DatabaseSeeder extends Seeder {
public function run()
{
Eloquent::unguard();
if (App::environment() === 'production')
{
$this->call('ProductionSeeder');
}
else
{
$this->call('StagingSeeder');
}
}
}
Of course, this solution works. But i am not sure that it is the right way to do this, because by inserting data using seeders you are losing all the advantages provided by the migration mechanism (database upgrate, rollback...)
I want to know what is the best practice in this case.
Laravel development is about freedom. So, if you need to seed your production database and think DatabaseSeeder is the best place to do so, why not?
Okay, seeder is mainly to be used with test data, but you'll see some folks using it as you are.
I see this important kind of seed as part of my migration, since this is something that cannot be out of my database tables and artisan migrate is ran everytime I deploy a new version of my application, so I just do
php artisan migrate:make seed_models_table
And create my seedind stuff in it:
public function up()
{
$models = array(
array('name' => '...'),
);
DB::table('models')->insert($models);
}
I've often found myself wondering what the right answer to this is. Personally, I'd steer clear of using seeding to populate required rows in the database as you'll have to put a load of conditional logic in to ensure that you don't attempt to populate something that's already there. (Deleting and recreating the data is very inadvisable as you could end up with key mismatches and if you're using cascading deletes you may accidentally wipe a load of your database by mistake! ;-)
I put the 'seeding' of rows into the migration script as the chances are, the data will need to be there as part of the rollout process.
It's worth noting that you should use the DB class instead of Eloquent models to populate this data as your class structure could change over time which will then prevent you from re-creating the database from scratch (without rewriting history and changing you migration files, which I'm sure is a bad thing.)
I'd tend to go with something like this:
public function up()
{
DB::beginTransaction();
Schema::create(
'town',
function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
}
);
DB::table('town')
->insert(
array(
array('London'),
array('Paris'),
array('New York')
)
);
Schema::create(
'location',
function (Blueprint $table) {
$table->increments('id');
$table->integer('town_id')->unsigned()->index();
$table->float('lat');
$table->float('long');
$table->timestamps();
$table->foreign('town_id')->references('id')->on('town')->onDelete('cascade');
}
);
DB::commit();
}
This then allows me to 'seed' the town table easily when I first create it, and won't interfere with any additions made to it at run-time.
This is what I use in production.
Since I run migration on each deployment
artisan migrate
I create a seeder (just to keep seeding data out of migration for easy access later) and then run that seeder along with the migration
class YourTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
//migrate your table // Example
Schema::create('test_table', function(Blueprint $table)
{
$table->increments('id');
$table->timestamps();
$table->softDeletes();
});
//seed this table
$seeder = new YourTableSeeder();
$seeder->run();
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('test_table');
}
}
I do not add this seed call to seeds/DatabaseSeeder.php to avoid running it twice on a new installation.
The Artisan Command Solution
Create a new artisan command
php artisan make:command UpsertConfigurationTables
Paste this into the newly generated file: UpsertConfigurationTables.php
<?php
namespace App\Console\Commands;
use Exception;
use Illuminate\Console\Command;
class UpsertConfigurationTables extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'upsert:configuration';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Upserts the configuration tables.';
/**
* The models we want to upsert configuration data for
*
* #var array
*/
private $_models = [
'App\ExampleModel'
];
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
foreach ($this->_models as $model) {
// check that class exists
if (!class_exists($model)) {
throw new Exception('Configuration seed failed. Model does not exist.');
}
// check that seed data exists
if (!defined($model . '::CONFIGURATION_DATA')) {
throw new Exception('Configuration seed failed. Data does not exist.');
}
/**
* seed each record
*/
foreach ($model::CONFIGURATION_DATA as $row) {
$record = $this->_getRecord($model, $row['id']);
foreach ($row as $key => $value) {
$this->_upsertRecord($record, $row);
}
}
}
}
/**
* _fetchRecord - fetches a record if it exists, otherwise instantiates a new model
*
* #param string $model - the model
* #param integer $id - the model ID
*
* #return object - model instantiation
*/
private function _getRecord ($model, $id)
{
if ($this->_isSoftDeletable($model)) {
$record = $model::withTrashed()->find($id);
} else {
$record = $model::find($id);
}
return $record ? $record : new $model;
}
/**
* _upsertRecord - upsert a database record
*
* #param object $record - the record
* #param array $row - the row of update data
*
* #return object
*/
private function _upsertRecord ($record, $row)
{
foreach ($row as $key => $value) {
if ($key === 'deleted_at' && $this->_isSoftDeletable($record)) {
if ($record->trashed() && !$value) {
$record->restore();
} else if (!$record->trashed() && $value) {
$record->delete();
}
} else {
$record->$key = $value;
}
}
return $record->save();
}
/**
* _isSoftDeletable - Determines if a model is soft-deletable
*
* #param string $model - the model in question
*
* #return boolean
*/
private function _isSoftDeletable ($model)
{
$uses = array_merge(class_uses($model), class_uses(get_parent_class($model)));
return in_array('Illuminate\Database\Eloquent\SoftDeletes', $uses);
}
}
Populate $_models with the Eloquent models you want to seed.
Define the seed rows in the model: const CONFIGURATION_DATA
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ExampleModel extends Model
{
use SoftDeletes;
const CONFIG_VALUE_ONE = 1;
const CONFIG_VALUE_TWO = 2;
const CONFIGURATION_DATA = [
[
'id' => self::CONFIG_VALUE_ONE,
'col1' => 'val1',
'col2' => 'val2',
'deleted_at' => false
],
[
'id' => self::CONFIG_VALUE_TWO,
'col1' => 'val1',
'col2' => 'val2',
'deleted_at' => true
],
];
}
Add the command to your Laravel Forge deployment script (or any other CI deployment script): php artisan upsert:configuration
Other noteworthy things:
Upsert Functionality: If you ever want to alter any of the seeded rows, simply update them in your model and it was update your database values next time you deploy. It will never create duplicate rows.
Soft-Deletable Models: Note that you define deletions by setting deleted_at to true or false. The Artisan command will handle calling the correct method to delete or recover your record.
Problems with other mentioned solutions:
Seeder: Running seeders in production is an abuse of the seeders. My concern would be that an engineer in the future would alter the seeders thinking that it's harmless since the documentation states that they are designed to seed test data.
Migrations: Seeding data in a migration is strange and an abuse of the purpose of the migration. It also doesn't let you update these values once your migration has been run.

Categories