In weird state with foreign key after migrations bug - laravel

I'm working on my first project using laravel 5. All my migration scripts create tables except for one that adds a foreign key constraint afterward (so both tables are in place before it runs). I found a bug in one of my migration scripts (missing parens made field non-nullable instead of nullable), so after fixing that, I tried doing php artisan migrate:refresh
I hit several errors, so I (mistakenly) decided to get to a fresh state by dropping the tables (using PostgreSQL Studio, via Heroku), but now I'm stuck in a weird state:
When I try php artisan migrate or php artisan migrate --force, it says "Nothing to migrate".
but when I try to rollback or reset or refresh, I get an error:
Undefined table: relation 'users' does not exist (SQL:alter table "users" drop constraint person_id)
That error is from that one migration script that adds the foreign key- I got the overall syntax from here- (http://laravel.com/docs/5.0/schema#foreign-keys)- scream out if wrong:
class AddConstraintToUsers extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->foreign('person_id')
->references('id')
->on('people');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropForeign('person_id');
});
}
}
More info: based on comment below I deleted the rows from the migrations table so they won't be listed as having already run (in hopes of helping the "Nothing to migrate"). After doing that and trying php artisan migrate I get the same 'relation "users" does not exist" error mentioned above, and now the migrations table shows a 'batch' value of 1 for create_users_table, and 2 for all the others.
Even crazier: since artisan runs migrations in order and thought it had nothing to run (but had been blocked from creating the users table), I created a new migration script to execute last, where the contents were creating that users table. At least it stopped telling me 'Nothing to migrate', BUT it gives a 'duplicate table' error for the OTHER table (called 'updates'), not the one I've actually tried to create twice :p
How can I get back to a normal place-(where either artisan finds my migration scripts to run fresh, or stops trying to rollback the change for the table that's no longer there)- I promise I've learned my lesson to not drop tables. Unfortunately it looks like this problem is less-google-able than usual (or I'm not using the right terms)- any help is greatly appreciated!!

In the end, the way out was to delete the migrations table too (not sure why deleting all the rows in it hadn't been sufficient, but at least I'm back in business now):
I dropped all the tables in my database, including the migrations table
I recreated the migrations table with artisan like so: php artisan migrate:install
Then migrations ran successfully, no problem: php artisan:migrate
Everything working again- hooray!

Related

How to transform an existing column in foreign key using Laravel Migrations

I'm having trouble trying to change a column type in laravel to fits it as a compatible column to be a foreign key referencing another table id fields.
I have a a schema like this:
Schema::create('person_organization', function(Blueprint $table){
...
$table->integer('organization_id');
...
});
and I want to change the field organization_id to an unsigned type, which will make it able to be a foreign key referencing the id field in the organizations table.
NOTE: Just changing the field type in the creation of the table is not an available option, because the system is running in production mode.
So we need to make a new migration to do these changes.
NOTE 2: i tried the method change as described in laravel docs, but it sticks in a query error, as following:
Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') on delete cascade' at line 1 (SQL: alter table person_organization add constraint person_organization_person_id_foreign foreign key (person_id) references persons () on delete cascade)
Considering you have already installed doctrine/dbal package in your application
Now create migration php artisan make:migration your_migration_name and then in migration insert the below code.
Schema::table('persons', function(Blueprint $table) {
$table->integer('organization_id')->unsigned()->index()->change();
$table->foreign('organization_id')->references('id')->on('organizations')-
>onDelete('cascade');
})
now run command php artisan migrate and now your are done.
Happy coding...
From Laravel 5.6 docs:
Before modifying a column, be sure to add the doctrine/dbal dependency to your composer.json file.
composer require doctrine/dbal
Then create the migration:
php artisan make:migration add_organization_foreign_to_persons_table --table=persons
And:
Schema::table('persons', function (Blueprint $table) {
$table->unsignedInteger('organization_id')->change();
$table->foreign('organization_id')->references('id')->on('organizations');
});
$table->integer('organization_id')->unsigned();
$table->foreign('organization_id')->references('id')->on('organizations')->onDelete('cascade');

Doubts over creating and running Laravel migrations

I've been reading the documentation, but I still have some doubts about creating migrations. On my project, I ran the migrate command to create Laravel's default tables (users, password_resets and migrations). Now I want to, one by one, create the migrations for the remaining tables I have planned on my EER diagram. My doubts are the following:
I can use the php artisan make:migration create_new_table to create a new migration and the --create=tablename complement is used to create a new table.
Will --create=tablename immediately create an empty the table on the DB?
Since I already have three tables, should I use --create=tablename for every new one?
After writing all the code, the migrate command will run all my migrations. Do I use this command after I've written migrations for all tables? Will running it again overwrite tables I already have on the DB?
It's probably basic stuff, but I want to be sure before going forward.
Will --create=tablename immediately create an empty the table on the DB?
No, table will be created when you run php artisan migrate. It will create a new migration with "boilerplate" for tablename. In this case, this will be added to the migration file:
Schema::create('tablename', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
Since I already have three tables, should I use --create=tablename for every new one?
It's really just a helper method for the boilerplate. So if you're creating a new one, it will make it easier.
Personally, I prefer creating migrations with php artisan make:model -m SomeModel, which will create the model and a boilerplate migration (because of -m option).
For example, if you run php artisan make:model SomeModel -m, it will a) create a model named SomeModel b) create a boilerplate migration (called somethinig like timestamp_create_some_models_table) with:
Schema::create('some_models', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
I like it because it's easy to stick to Laravels conventions this way (tables in plural, models in singular).
You can also add a namespace to the Model with the command. For example if you have your models in app/Models directory, you'd write php artisan make:model -m Models/SomeModel instead.
After writing all the code, the migrate command will run all my migrations. Do I use this command after I've written migrations for all tables? Will running it again overwrite tables I already have on the DB?
Laravel creates an SQL table specifically for logging which migrations have already run. It will not run the same migration twice, no matter how many times you execute php artisan migrate. Unless you roll them back with some command.
If a table already exists, it will just throw an SQL error saying, can't create a table, since it already exists.
there's no need to supply the table name, so this question is moot
No, you do not need to do this, see 1
migrate saves the name of each migration file in the migrations table and assigns it a batch id. Each subsequent migrate command will check for the existence of all file names in the table, and if they aren't present, will add it to the current batch before running the migrations defined within said file

Artisan skipping migrations

So, I've just pulled down a project in Laravel 5 from Github that I've done no work on before, but I need to set up to add a feature or three.
Problem is, I don't have any of the database tables for this project. That should be easy enough to fix, as the migrations are all there in the proper folder.
I run php artisan migrate and it tells me that there's a problem with one of the migrations trying to update a table that doesn't exist.
The problem is, that isn't the first migration by date. And an earlier migration should create the table it's saying isn't there yet.
Basically, it's something like this:
Migration 1
Migration 2
Migration 3
Migration 4
Migration 5 <--- here's where the error is occurring
Migration 6
etc....
It doesn't appear to be running migrations before the migration that throws an error at all, and it's not writing anything to the migrations table in that schema.
The error(s) I'm getting is:
[Illuminate\Database\QueryException]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'table1' doesn't exist (SQL: select * from `table1` where `code` = DEFAULT_ADDRESS limit 1)
and
[PDOException]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'table1' doesn't exist
Needless to say, I'm a bit confused as to why it would skip migrations, even ones that don't concern that table.
You should run:
php artisan migrate:status
It should show you migrations in the order they should be run. Make sure the order is valid. If it's not probably something was messed up it you might need to alter files to have valid order of your migrations.

How to create a column in laravel database without losing data

Suppose I have a table named "foo" with data and also contains foreign key. Now I want to create a column named "description" in this table. Without reset or rollback how to migrate this table?? Because If I reset or rollback the table then all data will be lost.
As per the docs, you just need to create a separate migration to create the new column.
Create the migration
php artisan make:migration add_description_to_foo
Then just set the migration up with the details you want to add, e.g:
Schema::table('foo', function ($table) {
$table->text('description');
});
Then you can just migrate it:
php artisan migrate
This will allow you to add a column without resetting or rolling back your tables, and thus prevent you from losing your data.
Let's start with your schema. Your table name is foo. You want to add a description column to your foo table without losing existing data. You need to create a new migration for this change.
php artisan make:migration add_columns_to_foo_table --table=foo
A new migration file will be created in your migrations directory. Open it and change it like this:
Schema::table('foo', function ($table) {
$table->text('description');
});
Save it and then run
php artisan migrate
description column will be created immediately without losing your old data as last column. In case you want to reposition your description column you need to use after (in case of MySQL) like this:
Schema::table('foo', function ($table) {
$table->text('description')->after('another_column');
});
Hope you got it.
You will find more details here: https://laravel.com/docs/5.3/migrations#creating-columns

How to migrate schema in Laravel without loss of existing data?

I have table named "user_table" has certain columns and table has filled with data. I want to add some more columns. So how can I migrate that new schema in Laravel without loss of existing data. Even I can not do rollback because when I will do then all stored data will be deleted. So, can somebody please help me to solve this issue ?
You can create new table columns in migrations without loss of data. If you alter a column or drop a column, then of course you will manipulate existing data. As long as you are only adding new columns, then you can run
php artisan make:migration alter_my_table_add_columns
and update your existing schema. Then you can safely run
php artisan migrate
In your new migration you would then add:
Schema::table('my_table', function ($table) {
$table->string('my_new_column');
});
See: https://laravel.com/docs/master/migrations#creating-columns

Resources