database migration is not working in yii - php

In Yii framework I used migration just like
./yiic migrate create tbl_demo
it made the migration file where I entered the values for up like
<?php
class m110714_094912_tbl_demo extends CDbMigration
{
public function up()
{
$this-> createTable('{{tbl_demo}}', array(
'id' => 'pk',
'name' => 'VARCHAR \'80\' NOT NULL',
))
}
public function down()
{
echo "m110714_094912_tbl_demo does not support migration down.\n";
return false;
}
/*
// Use safeUp/safeDown to do migration with transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}
after entering this it is showing message like
New migration created successfully.
But whenever I am checking mysql database there is no table for tbl_demo is found. I also put all the values of up in safeup but it not made any result.Every thing is working fine but don't know why new table is not creating? Please help me

You should go to the command line and call yiic migrate up and it will ask you if you want to apply the tbl_demo migration and when you type in "yes" it will execute the code. The message New migration created successfully. appears when you execute yiic migrate create -something- not when you apply the migration.
If you want to apply the migration again, you should delete the row regarding "tbl_demo" migration in the "migrations" db table that yiic created to log the migrations.

I just fixed this problem myself.
The answer is, the default /protected/config/console.php comes out of the box configured to use a SQLite database called testdrive.db. You have to configure it to talk to your MySQL database.

Related

How to rollback plugin's migration in OctoberCMS?

I has created plugin with one migration. My version.yaml is
1.0.1: First version of user
1.0.2:
- Added new fields to User model
- alter_table_users_add_contact_fields.php
My updates directory contains one migration file alter_table_users_add_contact_fields.php.
<?php
namespace Mnv\Reminder\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class CreateTableNewsRead extends Migration
{
protected $table = 'mnv_news_read';
public function up()
{
Schema::create($this->table, function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('news_id');
$table->foreign('news_id')->references('id')->on('rainlab_blog_posts')->onUpdate('cascade')->onDelete('cascade');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
$table->timestamp('read_at');
$table->index([
'news_id',
'user_id',
]);
$table->index([
'user_id',
'news_id',
]);
});
}
public function down()
{
Schema::dropIfExists($this->table);
}
}
I has successfully ran this migration using console command php artisan october:up.
But now I want to rollback this migration. As I see there is no informatino about this migration in table migrations. So I cant rollback this migration usins command php artisan migrate:rollback.
I found that information about plugin version contains in table system_plugin_versions. I has manually deleted my table mnv_news_read and manually deleted correspond records from system_plugin_versions and system_plugin_history tables.
drop table mnv_news_read;
delete from system_plugin_history where code = 'Mnv.Reminder';
delete from system_plugin_versions where code = 'Mnv.Reminder';
After that I tryed to run php artisan october:up again. It completed successfully.
My question is how to rollback plugin's migration correctly?
One way of rolling back migrations is via the builder plugin in admin control panel (make sure to install this plugin first if you have not already).
Select the builder plugin menu (from top of the page)
Select your plugin (by clicking on the arrow '>' button)
From left side menu, select Versions
Select the version you want to rollback
Click on the Rollback version button
According to documentation, you can run command in console:
php artisan plugin:rollback AuthorName.PluginName 1.2.3

CakePHP Migration Script doesn't update the Table Model

I need to add an admin column to my user table in my database. I created the migration script with the following command.
bin/cake bake migration AddAdminToUsers admin:boolean
This mostly did what I wanted, I just changed the default value to false. My Migration script now looks like this.
<?php
use Migrations\AbstractMigration;
class AddAdminToUsers extends AbstractMigration
{
public function change()
{
$table = $this->table('users');
$table->addColumn('admin', 'boolean', [
'default' => false,
'null' => false
]);
$table->update();
}
}
Also, oddly enough, I've tried this several times and each time I'm only able to run this migration script once. I have to delete it and re-bake a new one if I want another one to work.
When you run a migration it marks as migrated and you can not run it one more time unless do the rollback. Rollback will cancel previous migration and you will be able to run it one more time.Here is fully docs for plugin that cakphp using for migrations.

Use Laravel's migration to manage db schema from a single config file

I want to use Laravel's migration to manage my database. But I need to have a single configuration file where I store the schema. Something like this :
{
user: {
"id":"increments",
"name":"string",
"timestamps":"timestamps()"
}
}
And when I change this file again to the text below
{
user: {
"id":"increments",
"name":"string",
"password":"string",
"timestamps":"timestamps()"
}
}
I want to be able to run a command and have the database be changed without losing any data or creating an additional config file.
Can I achieve this using laravel migrations or if you know of any other solution that can help me and I would be able to use that on laravel without losing any of laravel's database management tools, please comment.
Thank you.
php artisan make:migration add_password_to_user ( are you sure the table is called user and not users? )
In your new migration
public function up()
{
Schema::table('user', function($table) {
$table->string('password');
});
}
Don't forget the rollback
public function down()
{
Schema::table('user', function($table) {
$table->dropColumn('password');
});
}
The table should be users if you have the model User .. otherwise make sure to have protected $table = 'user'; on the model.
https://laravel.com/docs/5.3/migrations
The --table and --create options may also be used to indicate the name of the table and whether the migration will be creating a new table. These options simply pre-fill the generated migration stub file with the specified table:
php artisan make:migration create_users_table --create=users
php artisan make:migration add_votes_to_users_table --table=users

Laravel migration transaction

When developing i'm having so many issues with migrations in laravel.
I create a migration. When i finish creating it, there's a small error by the middle of the migration (say, a foreign key constraint) that makes "php artisan migrate" fail. He tells me where the error is, indeed, but then migrate gets to an unconsistent state, where all the modifications to the database made before the error are made, and not the next ones.
This makes that when I fix the error and re-run migrate, the first statement fails, as the column/table is already created/modified. Then the only solution I know is to go to my database and "rollback" everything by hand, which is way longer to do.
migrate:rollback tries to rollback the previous migrations, as the current was not applied succesfully.
I also tried to wrap all my code into a DB::transaction(), but it still doesn't work.
Is there any solution for this? Or i just have to keep rolling things back by hand?
edit, adding an example (not writing Schema builder code, just some kind of pseudo-code):
Migration1:
Create Table users (id, name, last_name, email)
Migration1 executed OK. Some days later we make Migration 2:
Create Table items (id, user_id references users.id)
Alter Table users make_some_error_here
Now what will happen is that migrate will call the first statement and will create the table items with his foreign key to users. Then when he tries to apply the next statement it will fail.
If we fix the make_some_error_here, we can't run migrate because the table "items" it's created. We can't rollback (nor refresh, nor reset), because we can't delete the table users since there's a foreign key constraint from the table items.
Then the only way to continue is to go to the database and delete the table items by hand, to get migrate in a consistent state.
It is not a Laravel limitation, I bet you use MYSQL, right?
As MYSQL documentation says here
Some statements cannot be rolled back. In general, these include data
definition language (DDL) statements, such as those that create or
drop databases, those that create, drop, or alter tables or stored
routines.
And we have a recommendation of Taylor Otwell himself here saying:
My best advice is to do a single operation per migration so that your
migrations stay very granular.
-- UPDATE --
Do not worry!
The best practices say:
You should never make a breaking change.
It means, in one deployment you create new tables and fields and deploy a new release that uses them. In a next deployment, you delete unused tables and fields.
Now, even if you'll get a problem in either of these deployments, don't worry if your migration failed, the working release uses the functional data structure anyway. And with the single operation per migration, you'll find a problem in no time.
I'm using MySql and I'm having this problem.
My solution depends that your down() method does exactly what you do in the up() but backwards.
This is what i go:
try{
Schema::create('table1', function (Blueprint $table) {
//...
});
Schema::create('tabla2', function (Blueprint $table) {
//...
});
}catch(PDOException $ex){
$this->down();
throw $ex;
}
So here if something fails automatically calls the down() method and throws again the exception.
Instead of using the migration between transaction() do it between this try
Like Yevgeniy Afanasyev highlighted Taylor Otwell as saying (but an approach I already took myself): have your migrations only work on specific tables or do a specific operation such as adding/removing a column or key. That way, when you get failed migrations that cause inconsistent states like this, you can just drop the table and attempt the migration again.
I’ve experienced exactly the issue you’ve described, but as of yet haven’t found a way around it.
Just remove the failed code from the migration file and generate a new migration for the failed statement. Now when it fails again the creation of the database is still intact because it lives in another migration file.
Another advantage of using this approach is, that you have more control and smaller steps while reverting the DB.
Hope that helps :D
I think the best way to do it is like shown in the documentation:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
See: https://laravel.com/docs/5.8/database#database-transactions
I know it's an old topic, but there was activity a month ago, so here are my 2 cents.
This answer is for MySql 8 and Laravel 5.8
MySql, since MySql 8, introduced atomic DDL: https://dev.mysql.com/doc/refman/8.0/en/atomic-ddl.html
Laravel at the start of migration checks if the schema grammar supports migrations in a transaction and if it does starts it as such.
The problem is that the MySql schema grammar has it set to false. We can extend the Migrator, MySql schema grammar and MigrationServiceProvider, and register the service provider like so:
<?php
namespace App\Console;
use Illuminate\Database\Migrations\Migrator as BaseMigrator;
use App\Database\Schema\Grammars\MySqlGrammar;
class Migrator extends BaseMigrator {
protected function getSchemaGrammar( $connection ) {
if ( get_class( $connection ) === 'Illuminate\Database\MySqlConnection' ) {
$connection->setSchemaGrammar( new MySqlGrammar );
}
if ( is_null( $grammar = $connection->getSchemaGrammar() ) ) {
$connection->useDefaultSchemaGrammar();
$grammar = $connection->getSchemaGrammar();
}
return $grammar;
}
}
<?php
namespace App\Database\Schema\Grammars;
use Illuminate\Database\Schema\Grammars\MySqlGrammar as BaseMySqlGrammar;
class MySqlGrammar extends BaseMySqlGrammar {
public function __construct() {
$this->transactions = config( "database.transactions", false );
}
}
<?php
namespace App\Providers;
use Illuminate\Database\MigrationServiceProvider as BaseMigrationServiceProvider;
use App\Console\Migrator;
class MigrationServiceProvider extends BaseMigrationServiceProvider {
/**
* Register the migrator service.
* #return void
*/
protected function registerMigrator() {
$this->app->singleton( 'migrator', function( $app ) {
return new Migrator( $app[ 'migration.repository' ], $app[ 'db' ], $app[ 'files' ] );
} );
$this->app->singleton(\Illuminate\Database\Migrations\Migrator::class, function ( $app ) {
return $app[ 'migrator' ];
} );
}
<?php
return [
'providers' => [
/*
* Laravel Framework Service Providers...
*/
App\Providers\MigrationServiceProvider::class,
],
];
Of course, we have to add transactions to our database config...
DISCLAIMER - Haven't tested yet, but looking only at the code it should work as advertised :) Update to follow when I test...
Most of the answers overlook a very important fact about a very simple way to structure your development against this. If one were to make all migrations reversible and add as much of the dev testing data as possible through seeders, then when artisan migrate fails on the dev environment one can correct the error and then do
php artisan migrate:fresh --seed
Optionally coupled with a :rollback to test rolling back.
For me personally artisan migrate:fresh --seed is the second most used artisan command after artisan tinker.

Yii MySQL DB Migration trying to use SQLite

I'm creating a test application with Yii and have created my first migration.
<?php
class m111128_223507_reverse_bed_patient extends CDbMigration
{
public function up()
{
$this->dropForeignKey('fk_bed_patient1', 'bed');
$this->dropColumn('bed', 'patient_id');
$this->addColumn('patient', 'bed_id', 'int(11)');
$this->addForeignKey('fk_patient_bed1', 'patient', 'bed_id', 'bed', 'id', 'NO ACTION', 'NO ACTION');
}
public function down()
{
echo "m111128_223507_reverse_bed_patient does not support migration down.\n";
return false;
}
}
for some reason Yii thinks I'm using a SQLite db even though in my app main.php I have MySQL settings which works correctly everywhere else and the SQLite lines commented out.
I'm getting this error when I try my first migrate.
* applying m111128_223507_reverse_bed_patient
drop column patient_id from table bed ...exception 'CDbException' with message 'Dropping DB column is not supported by SQLite.' in ..
What am I missing here?
Probably your yiic tool is using console.php config file (as it is by default in Yii), try to review DB connection settings in protected/config/console.php.

Categories