Add multiple rows while migration - laravel

I am wondering is there a way to make 10-50 rows as default rows that could be added after migration in database?
In case I need to use php artisan migrate:fresh its pain to add simple values over and over again. Like I have Countries table where I need to add over and over again when I run migrate:fresh...
OR
Can I somehow exclude some tables from others that would be affected with command lines
Like inside create_countries_table:
DO_NOT_TOUCH_THIS_TABLE
Thanks
UPDATE:
Without routes etc. Just by migrations

Laravel has a great system about that, all you need to use database seeders.
For exaple you have a users table and you want to make some users.
First create a seeder using make:seeder command
php artisan make:seeder UsersTableSeeder
Then open your UsersTableSeeder and add these lines
public function run()
{
DB::table('users')->insert([
'name' => str_random(10),
'email' => str_random(10).'#gmail.com',
'password' => bcrypt('secret'),
]);
}
Then open your DatabaseSeeder class and add this line
public function run()
{
$this->call(UsersTableSeeder::class);
}
and run db:seed command
php artisan db:seed
For more further check out the seeding on laravel docs

Related

How to run Laravel Migrations, then Seeders, then more Migrations

I am re-building my Laravel app and, in the process, redesigning the data model.
I have a subset of my Migrations (35) I need to run to create the data model in the new app.
Then, I need to run some Seeders to populate the new tables.
Some of the new tables (12) have a column "old_id" where I place the "id" from the old data model to handle foreign keys/joins. I run a series of Update statements to change the foreign key values from the "old_id" to the new id.
Then, I want to run additional Migrations (12) that drop the "old_id" columns.
Here are the commands I'm running currently that do everything for me - clear DB, run migrations, populate data, and update keys.
php artisan migrate:reset
php artisan migrate:fresh --seed --seeder=DatabaseSeeder
I'm trying to find a way to only run a portion of my Migrations prior to executing DatabaseSeeder, and then run the remaining Migrations after (or as the last step of) the DatabaseSeeder.
Contents of DatabaseSeeder::class:
public function run()
{
$this->call([
// Seeders to populate data
UserSeeder::class,
AssociationSeeder::class,
... lots more classes ...
// Last Seeder class executes Update statements to update foreign keys
DatabaseUpdateSeeder::class,
]);
Thank you!
I ended up following the advice of the comment on the original post. While my previous "answer" also works, this is the right way to do it; separating round 1 and round 2 Migrations, and not executing Seeders from a Migration.
Here are my 2 commands (could be 3 if I wanted a separate command in the middle that only executes the Seeder), but adding the Seeder on the end of the command is supported syntax.
php artisan migrate:fresh --path=/database/migrations/batch-one --seed --seeder=DatabaseSeeder
php artisan migrate --path=/database/migrations/batch-two
I was able to achieve this by creating a Migration that calls my DatabaseSeeder. Here is how: https://owenconti.com/posts/calling-laravel-seeders-from-migrations
Then, after that Migration, I just have an additional Migration(s) to drop the "old_id" columns.
I also want to call out the comment from Tim on my original post with an alternative that would also work, but required multiple statements from the command line.

Bulk insert in migration not inserting data

As I've updated my postgres database scheme, I wanted to use a migration to migrate all existing data to the new tables in a migration, so it runs automagically when I deploy it to my host.
Unfortunately, that doesn't work. You'll find my code below. When I copy the exact same code to an artisan command, it works. When I copy that to artisan tinker, it works. When I run it via the migration, it doesn't. While DB#insert returns true, nothing gets inserted into the database.
I also tried calling the previously created working artisan command from the migration, but it doesn't insert any data then.
I've truncated the tables between the tests. Also the connection is correct as DB#getDefaultConnection returns the correct connection name and all other migrations work as expteced. Also another migration with DB#insert in it.
The weird thing: It worked a few weeks before. When I wrote this, I only made changes in the VueJS frontend, but not in the backend. I also haven't updated any packages or the postgres database. I am absolutely not sure what's going on there.
Also: No constraints are violated.
public function up()
{
$platform_id = DB::table('platforms')->where('slug', '[...]')->first()->id;
DB::table('apps')->chunkById(20, function ($apps) use ($platform_id) {
$transformed = [];
foreach ($apps as $app) {
echo "{$app->app_id} - {$app->name}\n";
$transformed[] = [
'uuid' => (string)Uuid::generate(4),
'platform_id' => $platform_id,
'remote_id' => $app→app_id,
// [...]
];
}
echo "Inserting...\n\n";
DB::table('products')->insert($transformed);
});
// [...]
// The same thing again with another table.

Current model is incompatible with old migrations

I have following sitation (I will describe it as history line):
I setup project witch User model (and users table) with migration file A
After some time i add user_modules table many-to-many and I was force to initialize this array during schama update in migration file B. I do it by
User::chunk(100, function($users) {
foreach ($users as $user) {
$user->userModule()->create();
}
});
After some time i need to update User model and table by add soft-delete (column delete_at) in migration file C and field $dates=['deleted_at'] in User model.
Then I develop system and add more migrations but at some point new developer join to our team and he must build DB schema from scratch so he run php artisan:migrate but he get error in migration file B:
[Illuminate\Database\QueryException (42S22)]
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'users.deleted_at' in 'where clause' (SQL: select * from users
where users.deleted_at is null order by users.id asc limit 100
off set 0)
So the current User model is incompatible witch migration file B
How to deal with that situation?
Where I made mistake and what to do to prevent such situation in future?
This is because of Soft Deletes. When you add the trait SoftDeletes to a model, it will automatically add where users.deleted_at is null to all queries. The best way to get around this is to add withTrashed() to your query in migration B.
To do this, change your query in migration B to look like the following. This should remove the part where it's trying to access the non existent deleted_at column. This migration, after all, is not aware that you want to add soft deletes later on, so accessing all users, including those that are trashed, makes perfect sense.
User::withTrashed()->chunk(100, function($users) {
foreach ($users as $user) {
$user->userModule()->create();
}
});
You could always comment out the SoftDelete trait on the user model before running the migrations also, but that's a temporary fix since you'll need to explain it to all future developers. Also, it can be very handy to run php artisan migrate:fresh sometimes. You don't want to have to remember to comment out the trait each time, so adding withTrashed() seems like the most desirable solution to me.
As a final note, I highly suggest NOT adding seeds to your migrations. Migrations should ONLY be used for schema changes. In cases like this, I would use a console command, or a combination of console commands.
For example, you could make a console command that gets triggered by php artisan check:user-modules. Within this command, you could have the following which will create a user module only if one does not yet exist.
User::chunk(100, function($users) {
foreach ($users as $user) {
if (!$user->userModule()->exists()) {
$user->userModule()->create();
}
}
});
You should be able to run this command at any time since it won't overwrite existing user modules.
Alternative answer: In such situation when we need to generate or transform some data after db schema change - we should NOT use Models (which can independently change in future) but instead use inserts/updates:
DB::table('users')->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('user_modules')->insert(
['user_id' => $user->id, 'module_id' => 1]
);
}
});
As it is written in laravel documentation, seeders are designed for data seeding with test data but not for data transformation - so migration files are probably good place to put transformation code (which can generate or change some production data in DB after schema update)
Laravel includes a simple method of seeding your database with test data using seed classes.
Add this to your old migration queries
use Illuminate\Database\Eloquent\SoftDeletingScope;
User::withoutGlobalScope(new SoftDeletingScope())

Setting default value for Laravel Migration

I am using Laravel 5.6 and has a multi-auth funcitonality and it works fine. I have user and admin tables in my DB. How can i set a default value on admin table like NAME, EMAIL and PASSWORD? So everytime i run php artisan migrate:refresh i will have the default NAME EMAIL and PASSWORD in admin table? Thank you!
Without a little clarification there are two possible answers to your question. If you are asking about columns in your database tabled having default values this has already been answered but it is simply by chaining the method default on your attribute.
$table->tinyInteger('status')->default('1');
If you are asking about populating a row in your database whenever you migrate refresh. You can use seeders:
Laravel includes a simple method of seeding your database with test
data using seed classes. All seed classes are stored in the
database/seeds directory. Seed classes may have any name you wish, but
probably should follow some sensible convention, such as
UsersTableSeeder, etc. By default, a DatabaseSeeder class is defined
for you. From this class, you may use the call method to run other
seed classes, allowing you to control the seeding order.
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
DB::table('users')->insert([
'name' => 'default_name',
'email' => 'default#mail.com',
'password' => 'password',
]);
}
}
And afterwards just call:
php artisan migrate:refresh --seed

Receiving [Illuminate\Database\Eloquent\MassAssignmentException] email using Laravel 5.5

Am following a tutorial attempting to learn how to use Laravel5.5. After following a step which said to add protected $fillable = array('email', 'password', 'name'); to the User model.
Which I'm assuming is setting which fields are mass assignable fields? The next step was to add:
User::create(array(
'email' => 'your#email.com',
'password' => Hash::make('password'),
'name' => 'John Doe'
));
Which I'm to understand is to add said user to the db.
When I run php artisan migrate I receive [Illuminate\Database\Eloquent\MassAssignmentException] email and I have no idea why. I have tried adding Eloquent::unguard(), have tried to make it all guardable.
Have removed email from the fillable array. Have got rid of email altogther.
Each time I run php artisan migrate the error is this same.
It should work without any problems based on your description.
So make sure:
you are using valid User model (maybe you have 2 and you set fillable only in one of them)?
you are not inserting other data in migrations. It's quite possible the problem is for other model and not for User model.

Resources