How to seed pivot table in Laravel 5.4? - php

I am following a tutorial called Incremental API in laracasts by Jeffrey Way.
There is a different coding between Laravel 4 faker class seeding and laravel 5.4.
I still followed the same code lines from the tutorials "Seeders Reloaded". Now, I am stuck with "Class LessonTagTableSeeder does not exist"
TagTableSeeder
class TagsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$faker = Faker::create('App\Tag');
for($i=1; $i <= 10; $i++) {
DB::table('tags')->insert([
'name' => $faker->word,
'created_at' => \Carbon\Carbon::now(),
'updated_at' => \Carbon\Carbon::now(),
]);
}
}
LessonTagTableSeeder
use Illuminate\Database\Seeder;
use Faker\Factory as Faker;
use App\Lesson;
use App\Tag;
class LessonTagTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$faker = Faker::create();
$lessonIds = Lesson::pluck('id')->all();
$tagIds = Tag::pluck('id')->all();
for($i=1; $i <= 30; $i++) {
DB::table('lesson_tag')->insert([
'lesson_id' => $faker->randomElement($lessonIds),
'tag_id' => $faker->randomElement($tagIds)
]);
}
}
DatabaseSeeder
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use App\Lesson;
use App\Tag;
use DB;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0');
Lesson::truncate();
Tag::truncate();
DB::table('lesson_tag')->truncate();
Model::unguard();
$this->call('LessonsTableSeeder');
$this->call('TagsTableSeeder');
$this->call('LessonTagTableSeeder');
DB::statement('SET FOREIGN_KEY_CHECKS=1');
}
I was able to seed TagsTableSeeder with php artisan db:seed --class=TagsTableSeeder
When i run "php artisan db:seed --class=LessonTagTableSeeder" , i am prompted with:
[ReflectionException]
Class LessonTagTableSeeder does not exist
Do you have any idea how to edit the code above? Any help is appreciated

When you make changes into the seeder files and it does not reflects your changes you need to run composer dump autoload.
you can use any one of the following commands
$ composer dump-autoload
$ composer du
$ composer dump
$ composer dump-autoload -o
Then try to run you command db:seed again and it reflects you changes.
what composer dump autoload do?
composer dump-autoload won’t download a thing. It just regenerates the list of all classes that need to be included in the project (autoload_classmap.php). Ideal for when you have a new class inside your project.
Ideally, you execute composer dump-autoload -o , for a faster load of your webpages. The only reason it is not default, is because it takes a bit longer to generate (but is only slightly noticeable)

Make sure the file is named as LessonTagTableSeeder.php and it's in the same directory as the other seeders. Then run this command:
composer du
After that try to execute the seeder again.

run this command and then try again
composer dump-autoload -o

Usually cache
php artisan cache:clear
composer update
php artisan serve

A pivot table, or association table, is a table which maps the relationship between two other tables, very useful for two tables which have a many-to-many relationship.
There are 3 critical lines of code which you supplied for the 'DatabaseSeeder':
$this->call('LessonsTableSeeder');
$this->call('TagsTableSeeder');
$this->call('LessonTagTableSeeder');
Based on what you wrote, you only ran the commands for the 'TagsTableSeeder' and the 'LessonTagTableSeeder'. You missed running the command for 'LessonsTableSeeder'.
In other words, you had records in the 'Tag' table, but none in the 'Lesson' table. Therefore there were no records associated between the two tables and SQL couldn't create a null association (pivot) table.
As a further note, the order of execution for seed operations is important when creating an association table. You must execute the seed command for the association table AFTER seeding the other two tables. The association table needs to know the unique identifiers in each of the other tables in order to create the relationships.

Related

How to migrate tables in order in Laravel? [duplicate]

Is there a way how I can change the migrations order without remaking them all? Because now I have a problem with my foreign keys -_- (working with laravel)
Roll back all the migrations (or start with a fresh database);
Change the dates that form the first part of the migration filenames so they're in the order you want (eg. for 2014_06_24_134109_update_database.php, the date & time is 2014-06-24, 13:41:09);
Run the migrations again.
With respect to your comment about foreign keys... I'm not sure that the problem is with Laravel. More likely, it's just MySQL.
I avoid foreign keys because once you get a moderately complicated set of relations, you start to run into problems with database consistency like you're seeing - it's hard for the server to figure out what order to create the tables & relationships in, and it starts to cause difficulties with things like dump files (for backups).
You have to create a custom command that executes
php artisan migrate:refresh --path=/database/migrations/name_migration.php repeately with the migrations's name in the order you want.
Like this:
Create Command class with: php artisan make:command NameClass
Go to app/Console/Commands/ and find the class file NameClass.php
In the NameClass.php you have two attributes $signature (the name of the command) and $description (Information about what your command does).
Set the name and the description of your command.Ex: protected $signature='namecommand'; protected $descripton = 'This method migrate tables in order'
Inside the NameClass.php you have a method called handle(), here you have to declare the code you want to be executed when you write the command.
Register your command. Go to app/Console/Kernel.php and add your class to the list of Command Classes.
protected $commands = [
Commands\NameClass::class,
];
Write the command in the terminal. php artisan namecommand
Example:
php artisan make:command MigrateInOrder
app/Console/Commands/MigrateInOrder.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class MigrateInOrder extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'migrate_in_order';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Execute the migrations in the order specified in the file app/Console/Comands/MigrateInOrder.php \n Drop all the table in db before execute the command.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
/** Specify the names of the migrations files in the order you want to
* loaded
* $migrations =[
* 'xxxx_xx_xx_000000_create_nameTable_table.php',
* ];
*/
$migrations = [
'2020_04_18_005024_create_users_types.php',
'2014_10_12_000000_create_users_table.php',
'2014_10_12_100000_create_password_resets_table.php',
'2019_08_19_000000_create_failed_jobs_table.php'
];
foreach($migrations as $migration)
{
$basePath = 'database/migrations/';
$migrationName = trim($migration);
$path = $basePath.$migrationName;
$this->call('migrate:refresh', [
'--path' => $path ,
]);
}
}
}
Go to app/Console/Kernel.php and register your command
protected $commands = [
Commands\MigrateInOrder::class,
];
Excute the command
php artisan migrate_in_order
Taking inspiration from PhpMyAdmin, I put all foreign keys definitions in a specific far future file, eg : 2999_12_31_235959_foreign_key.php
<?php
use App\Models\Post;
use App\Models\Tag;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ForeignKeys extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
// Post_tag
Schema::table(Post::NOM, function (Blueprint $table) {
$table->foreign('id_post')
->references('id_post')
->on(Post::NOM);
$table->foreign('id_tag')
->references('id_tag')
->on(Tag::NOM);
});
}
}
The only con I see is not having foreign keys definition in migration.
For the pros :
Keeping database relations
Do not care of table creation order
The best and easiest thing would be to just rename the migration yyyy_mm_dd_hhmmss_migration_name. If your migration follows this sequence, Laravel will ensure to run the migration is sorted form of date,
Building on the answer of Galeokerdo which suggests creating a separate migration file for the foreign keys, and putting the date in the far future, I tried it and it worked great. But then I started thinking of the rollback. It turned out that Laravel takes the reverse order when rolling back migrations. That is, the latest file is rolled back first.
Since the rollback will not work with the foreign key constraints in place, I tried putting my foreign-key-removal code in the "down" method of the separate foreign key migration, having found out that the file will execute first before all other migration files. Like thus:
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('tablename', function (Blueprint $table) {
$table->dropForeign('tablename_foreignkey_foreign');
});
}
"tablename_foreignkey_foreign" is the name of the foreign key constraint. By default, it is
"nameofthetable_foreignkeycolumn_foreign"
I just wanted to share this in case anybody is struggling with it the way I did.
You only need to change migrations order. if bands or stage tables are below users table, MySQL don't find the references. =)

How to run laravel migration and DB seeder except one

I am having many migration and seeder files to run, Although I will need to run all files but currently I need to skip one migration and seeder.
How could I skip one file from laravel migration and db seeder command.
I do not want to delete files from the migrations or seeds folder to skip the file.
Laravel doesn't give you a default method to do it. However, you can create your own console commands and seeder to achieve it.
Let's say you have this default DatabaseSeeder class:
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(ExampleTableSeeder::class);
$this->call(UserSamplesTableSeeder::class);
}
}
the goal is to create a new command overriding "db:seed" and pass a new parameter, an "except" parameter, to the DatabaseSeeder class.
This is the final code, I created on my Laravel 5.2 instance and tried:
Command, put in app/Console/Commands, don't forget to update your Kernel.php:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SeedExcept extends Command
{
protected $signature = 'db:seed-except {--except=class name to jump}';
protected $description = 'Seed all except one';
public function handle()
{
$except = $this->option('except');
$seeder = new \DatabaseSeeder($except);
$seeder->run();
}
}
DatabaseSeeder
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
protected $except;
public function __construct($except = null) {
$this->except = $except;
}
public function call($class)
{
if ($class != $this->except)
{
echo "calling $class \n";
//parent::call($class); // uncomment this to execute after tests
}
}
public function run()
{
$this->call(ExampleTableSeeder::class);
$this->call(UserSamplesTableSeeder::class);
}
}
It the code, you'll find that I commented the line that calls the seed and added an echo for testing purposes.
Executing this command:
php artisan db:seed-except
will give you:
calling ExampleTableSeeder
calling UserSamplesTableSeeder
However, adding "except":
php artisan db:seed-except --except=ExampleTableSeeder
will give you
calling UserSamplesTableSeeder
This works overriding the default call method of your DatabaseSeeder class and calling the parent only if the name of the class is not in the $except variable. The variable is populated by the SeedExcept custom command.
Regarding migrations, the thing is similar but a little bit more difficult.
I can't give you tested code for this by now, but the thing is:
you create a migrate-except command that overrides the MigrateCommand class (namespace Illuminate\Database\Console\Migrations, located in vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php).
the MigrateCommand takes a Migrator object (namespace Illuminate\Database\Migrations, path vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php) in the constructor (injected via IoC). The Migrator class owns the logic that reads all the migrations inside the folder and execute it. This logic is inside the run() method
create a subclass of Migrator, for example MyMigrator, and override the run() method to skip the files passed with the special option
override the __construct() method of your MigrateExceptCommand and pass your MyMigrator: public function __construct(MyMigrator $migrator)
If I have time I'll add the code for an example before the bounty ends
EDIT
as promised, here's an example for migrations:
MyMigrator class, extends Migrator and contains the logic to skip files:
namespace App\Helpers;
use Illuminate\Database\Migrations\Migrator;
class MyMigrator extends Migrator
{
public $except = null;
// run() method copied from it's superclass adding the skip logic
public function run($path, array $options = [])
{
$this->notes = [];
$files = $this->getMigrationFiles($path);
// skip logic
// remove file from array
if (isset($this->except))
{
$index = array_search($this->except,$files);
if($index !== FALSE){
unset($files[$index]);
}
}
var_dump($files); // debug
$ran = $this->repository->getRan();
$migrations = array_diff($files, $ran);
$this->requireFiles($path, $migrations);
//$this->runMigrationList($migrations, $options); // commented for debugging purposes
}
}
The MigrateExcept custom command
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Console\Migrations\MigrateCommand;
use App\Helpers\MyMigrator;
use Illuminate\Database\Migrations\Migrator;
use Symfony\Component\Console\Input\InputOption;
class MigrateExcept extends MigrateCommand
{
protected $name = 'migrate-except';
public function __construct(MyMigrator $migrator)
{
parent::__construct($migrator);
}
public function fire()
{
// set the "except" param, containing the name of the file to skip, on our custom migrator
$this->migrator->except = $this->option('except');
parent::fire();
}
// add the 'except' option to the command
protected function getOptions()
{
return [
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],
['path', null, InputOption::VALUE_OPTIONAL, 'The path of migrations files to be executed.'],
['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run.'],
['seed', null, InputOption::VALUE_NONE, 'Indicates if the seed task should be re-run.'],
['step', null, InputOption::VALUE_NONE, 'Force the migrations to be run so they can be rolled back individually.'],
['except', null, InputOption::VALUE_OPTIONAL, 'Files to jump'],
];
}
}
Last, you need to add this to a service provider to permit the Laravel IoC resolve the dependencies
namespace App\Providers;
use App\Helpers\MyMigrator;
use App\Console\Commands\MigrateExcept;
class CustomServiceProvider extends ServiceProvider
{
public function boot()
{
parent::boot($events);
$this->app->bind('Illuminate\Database\Migrations\MigrationRepositoryInterface', 'migration.repository');
$this->app->bind('Illuminate\Database\ConnectionResolverInterface', 'Illuminate\Database\DatabaseManager');
$this->app->singleton('MyMigrator', function ($app) {
$repository = $app['migration.repository'];
return new MyMigrator($repository, $app['db'], $app['files']);
});
}
}
Don't forget to add Commands\MigrateExcept::class in the Kernel.php
Now, if you execute
php artisan migrate-except
you have:
array(70) {
[0] =>
string(43) "2014_04_24_110151_create_oauth_scopes_table"
[1] =>
string(43) "2014_04_24_110304_create_oauth_grants_table"
[2] =>
string(49) "2014_04_24_110403_create_oauth_grant_scopes_table"
...
but adding the except param:
php artisan migrate-except --except=2014_04_24_110151_create_oauth_scopes_table
array(69) {
[1] =>
string(43) "2014_04_24_110304_create_oauth_grants_table"
[2] =>
string(49) "2014_04_24_110403_create_oauth_grant_scopes_table"
So, recap:
we create a custom migrate-except command, MigrateExcept class, extending MigrateCommand
we create a custom migrator class, MyMigrator, extending the behavior of the standard Migrator
when MigrateExcept is fire(), pass the name of the file to skip to our MyMigrator class
MyMigrator overrides the run() method of Migrator and skip the passed migration
More: since we need to instruct Laravel IoC about the new created classes, so it can inject them correctly, we create a Service Provider
The code is tested so it should work correctly on Laravel 5.2 (hoping that cut&paste worked correctly :-) ...if anyone has any doubt leave a comment
Skipping seeds are very simple, migrations not so much. To skip a seed, remove the following from your DatabaseSeeder class.
$this->call(TableYouDontWantToSeed::class);
For migrations, There are three ways you can do it:
Put the class you don't want to migrate into a different folder.
Insert your migrations into the database manually (Bindesh Pandya's answer elaborated).
Rename the file that you don't want to migrate to something like UsersTableMigration.dud.
Hope this helps
I also faced the same problem in my project but after long time wasting in R & D i have found that Laravel does not provide any way to do this with migration and seeding but you have 2 ways to do this.
1) you'll save a lot of time just putting them into different folders.
You could theoretically make your own artisan command that does what
you want, or spoofs its by making directories, moving files, and running
php artisan migrate.
For the seeders, just make a seeder and call the others seeders you want to run from with in it. Then just be explicit about what seeder you want to run. Try php artisan db:seed --help for more details there.
2) you can create a table Manually (which has same name as migration table is creating in you db) and insert the values of migration like this
insert into migrations(migration, batch) values('2015_12_08_134409_create_tables_script',1);
so migrate command will not create table which is already exist in migration table.
If you want just omit (but keep) migration and seeder:
Rename your migration by removing .php extension: mv your_migration_file.php your_migration_file
Go to: DatabaseSeeder.php and comment out line with your unwanted seeder: //$this->call('YourSeeder');.
Run: php artisan migrate --seed
Execute below sql query on db (be careful, there should be migration file name WITHOUT extension) (this will prevent artisan migrate to execute your_migration_file in future):
INSERT INTO migrations (migration, batch) VALUES (your_migration_file, 1)
Rename back your migration file: mv your_migration_file your_migration_file.php
Uncomment your seeder in DatabaseSeeder.php
And you are done. Now when you run php artisan migrate any migration should be executed (except new one if you add some new migration files).
just an idea comment seeder and schema. this is the way i guess
//$this->call(HvAccountsSeeder::class);
//Schema::create('users', function (Blueprint $table) {
// $table->increments('id');
// $table->string('name');
// $table->string('email')->unique();
// $table->string('password');
// $table->rememberToken();
// $table->timestamps();
// });
// Schema::drop('users');
To directly answer your question, Laravel does not have a way to do this currently.
If I understand you correctly, I assume you're looking for a way to temporarily disable/skip a specific class from the default DatabaseSeeder.
You can easily create your own command which will accept a string such as a model/table name and attempt to run the migration and seed for that particular table. You will simply need something like the following:
public function handle(){ //fire for Laravel 4.*
$tables = explode(',', $this->option('tables'));//default []
$skip = explode(',', $this->option('skip'));//default []
$migrations = glob("*table*.php");//get all migrations
foreach($migrations as $migrate){
//if tables argument is set, check to see if part of tables
//if file name not like any in skip.. you get the point

Laravel 5 migration refuses to run

I'm growing desperate, I need help! I've been at this all day!
I want to configure a DB in Laravel. I have all my migrations (in order) so no foreign key will conflict and hit a table that would only be created later.
But no matter what I try I keep hitting an error that says this,
http://prntscr.com/6z23nw
EDIT: now it says the exact same thing but that the class was 'not found'... I'm totally clueless here....
A bit more information, (I was going to post a screenshot but I can't)... searching for usages of GroupUser all I can find is the one I posted and entries in the laravel.log (listed as non-code usage). So there really is no other "groupUser" class
Here's a screenshot of my migrations folder.
These are my migrations they run in order and all tables until GroupUser are properly created
the migration that's causing all this mess
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class GroupUser extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('group_user', function(Blueprint $table)
{
$table->integer('user_id')->unsigned();
$table->integer('group_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('group_id')->references('id')->on('groups');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('group_user');
}}
One final note I completely erased all the previous migrations and even tried reinstalling with the php artisan migrate:install
Run composer dump-autoload. After creating the migration files via artisan, you need to re-run composer to have them be autoloaded automatically.
Solved the issue,
. migrate:reset to set everything from blank
. created migrations with the tables but no foreign keys and dependencies
. php artisan migrate (all worked out fine)
. created new migrations altering the tables required with the foreign keys.
. again 'php artisan migrate'
I think it all worked fine. Thank you for your help and ideas everyone!

Laravel Seeding error

I am trying to seed some info on my oneway table but evertime I run php artisan db:seed, an error would occur
{"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","me
ssage":"Class 'Oneway' not found","file":"C:\\wamp\\www\\airlines\\app\\database
\\seeds\\OnewayTableSeeder.php","line":8}}
I have tried composer dump-autoload but still nothing happens. What seems to be the problem here?
Is it on my composer or my codes.
OnewayTableSeeder.php
<?php
class OnewayTableSeeder extends Seeder{
public function run()
{
DB::table('oneway')->delete();
Oneway::create(
array(
'destination-from'=>'Bacolod',
'destination-to'=>'Cebu',
'departure'=> \Carbon\Carbon::createFromDate(2014,10,01)->toDateTimeString(),
));
Oneway::create(
array(
'destination-from'=>'Tawi-Tawi',
'destination-to'=>'Cebu',
'departure'=> \Carbon\Carbon::createFromDate(2014,10,03)->toDateTimeString(),
));
Oneway::create(
array(
'destination-from'=>'Cebu',
'destination-to'=>'Dipolog',
'departure'=> \Carbon\Carbon::createFromDate(2014,10,16)->toDateTimeString(),
));
}
}
DatabaseSeeder.php
<?php
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Eloquent::unguard();
// $this->call('UserTableSeeder');
$this->call('OnewayTableSeeder');
}
}
There is someone else who had a similar problem with migrations.
Laravel 4 migration: class not found exception
This might just work for you.
Other than this, make sure you have a model for OneWay and also make sure that the seeder file is named exactly OnewayTableSeeder.php. Moreover try using this package fzaninotto/Faker
to seed your database. I know that the library isn't relevant to the question you asked but it comes in very handy.
Also I personally tried removing either the model or the seeder file and it gives me a different exception than yours. All I can find everywhere is that the seeder file was not included and you should run composer dump-autoload or composer dumpautoload. Try both of them just for the sake of it.

How to have conditional database seeding in Laravel?

Can I create seed groups? For instance I have seeds that I only want executed some of the time. How can I add a flag when executing php artisan migrate --seed --group1
What are my options for such feature?
Well, what you could do is create multiple Seeder extended classes, and having each one of them running $this->call() on a specific group of tables and then specify which one you want using the --class flag. Something like this:
class GroupOneDatabaseSeeder extends Seeder {
public function run() {
Eloquent::unguard();
$this->call('UserTableSeeder');
$this->call('RoleTableSeeder');
}
}
And then call it this way:
php artisan db:seed --class="GroupOneDatabaseSeeder"
Well, that or you could extend the SeedCommand to add this functionality via methods instead of classes.

Categories