I'm creating a SAAS application with multi tenant databases. So, whenever a person registers on the site. I'm creating a database on run time and then after a connection on the fly. I want to run the migrations to create tables in the new database.
Everything is working fine but the migrations are not happening.
Here is my code which calls my migration:
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true));
I'm already creating the migrations tables before calling this command.
Try with this:
Artisan::call('migrate',
[
'--database' => 'tenant',
'--path' => 'database/migrations',
'--step' => true,
'--force' => true
]);
Replace tenant with your database connection name.
Related
Laravel migrations need to be run with a particularly high level of privilege, as they perform DDL operations. I would like to run migrations as a named user without storing the password anywhere. This will require prompting the user for their password when they run the migration from the command-line. I cannot find any way to achieve this via connection configuration.
Is there a way to achieve this via the connection configuration?
If not, is there a way to perform the migrations with a thin layer of custom code over the top to establish the database connection in a custom manner? e.g. write a script/artisan command that does the prompting, connects to the DB, and then delegates the rest to Laravel's existing migration code?
If your requirement is to just ask the user for database credentials in order to run the migrations, then this can very easily be achieved by wrapping the artisan migrate command within another command that asks for appropriate credentials. So the steps below should suffice:
1. Create the new command:
artisan make:console MigratePrivilegedCommand --command="migrate:privileged"
2. Add the necessary code to handle user input and run the migrations in your new command class:
class MigratePrivilegedCommand extends Command
{
protected $signature = 'migrate:privileged';
protected $description = 'Run migrations as a priviledged database user.';
public function __construct()
{
parent::__construct();
}
public function handle()
{
// Set the username and password for the
// database connection from user input
config([
'database.connections.mysql.username' => $this->ask('What is your username?'),
'database.connections.mysql.password' => $this->secret('What is your password?')
]);
// Call the migrate command and you're done
$this->call('migrate');
}
}
3. Register the new command in App\Console\Kernel.php:
protected $commands = [
...
\App\Console\Commands\MigratePrivilegedCommand::class,
];
And now you can run migrations that need privileged database credentials with this:
php artisan migrate:privileged
You can set a custom connection without any password in the config file and pass the password via CLI command to run the migrations.
In database.php config
'connection_without_password' => [
'driver' => 'mysql',
'host' => 'hostname,
'database' => 'database',
'username' => '$username',
'password' => '$password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
Schema class includes a connection name option.
Schema::connection('connection_without_password')->create('users', function ($table) {
$table->increments('id');
});
I have a large project which will have each customer on their own separate database. To get this to work we use a custom .env-loader that loads each customers .envby checking the customers subdomain (unique to each customer).
However, of course this doesn't work with artisan commands. For instance, when I want to migrate, I will need to migrate all databases at once. So I've set up an Artisan command that fetches the .env-files and loop through them and then calls the default artisan migrate. But it is not working as expected.
I've tried everything; for instance:
$dotenv = new Dotenv('/env', '.test.env');
$dotenv->overload();
And:
app()->useEnvironmentPath('/env');
app()->loadEnvironmentFrom('.test.env');
And even:
config('database.connections.mysql.database', 'test_database');
As soon as I run $this->call('migrate'); the app defaults to the default .env and ignores all customizations at runtime. Does anyone have an idea on how I can overload the migration commands choice of database?
Note: I know that I can manually setup multiple connections in config/database.php (for instance like: Overriding Default Laravel database configuration for artisan migrate commands), however, image a few dozen customers and this would not be viable.
I had to do something similar with SQLite database that were being created by the console commands, and the only way I could get the migrations to run was by creating a database config on the fly:
Config::set('database.connections.'.$config_key, array(
'driver' => 'sqlite',
'database' => storage_path($database_name),
'prefix' => '',
));
And then I would call the migrate command:
Artisan::call('migrate', [
'--database' => $config_key,
'--path' => 'database/offline/'.$type.'/migrations',
]);
After a whole lot of issues I was able to sort it this way;
In Laravel 5 there seem to be a difference in Config::set(), config('config',['key' => 'value]) and config()-set('config', ['key' => 'value']).
After a lot of testing different variant we managed to get a solution this way;
$connection = 'connection';
$iterator = 0;
foreach ($files as $file) {
App::useEnvironmentPath('/env');
App::loadEnvironmentFrom('.file.env');
// Create a new connection "on the fly"
config()->set('database.connections.' . $connection . '_' . $iterator, [
'driver' => 'mysql',
'host' => env('DB_HOST'),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]);
// Call regular migration command
$this->call('migrate', ['--force' => true, '--database' => $connection . '_' . $iterator]);
$iterator++;
}
This manages to set multiple new connections to the MySQL-database, and then seed each one of them.
Thanks to #David Allen here for the inspiration.
I have used symfony2 console to create database. If I want to create a database named "symfony" I usually mentioned that name in parameters.yml file and run the below command in console
php app/console doctrine:database:create
But when came to laravel, I don't find similar command to create database in laravel. Can anyone help me to find out those command to create database directly from Laravel Console.
You can do that but you will have to create your own command.
First, run php artisan command:make CreateDatabase --command=database:create to generate app/commands/CreateDatabase.php
Then open that file and change it to this: (I left out all comments, but you can obviously keep them in there)
class CreateDatabase extends Command {
protected $name = 'database:create';
protected $description = 'Command description.';
public function fire()
{
DB::statement('CREATE DATABASE '.$this->argument('name'));
}
protected function getArguments()
{
return array(
array('name', InputArgument::REQUIRED, 'Database name'),
);
}
}
Now you only have to register the command in app/start/artisan.php:
Artisan::add(new CreateDatabase);
and you're good to go.
That's how you call it:
php artisan database:create your-desired-database-name
Alternative: artisan tinker
You can always use php artisan tinker to run PHP code (with Laravel bootstrapped):
php artisan tinker
> DB::statement('CREATE DATABASE your-desired-database-name');
As far as I know, you can use php artisan migrate to make migrations including creating tables from Laravel Console. However, you need to create and modify migration files first, where you can create or drop tables.
So if you want to create a table directly from Laravel Console using something like php artisan create database table ***, it is not possible.
I think you can not create database through command so go to app/config/database.php and set your database configuration. details here
'mysql' => array(
'read' => array(
'host' => '192.168.1.1',
),
'write' => array(
'host' => '196.168.1.2'
),
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
after setting you can create table through command
php artisan migrate:make create_user_table --table=users
it will generate a file to app/database/migrations name create_users_table. . . . . then you create your table following this link
and finally run this command php artisan migrate
I have successfully configured a second database with codeigniter and was able to create a table. The problem is now that every previously existing lines of code that was using $this->db now uses the second database so naturally it pops an error. Let me explain with a bit more details:
I use the migration library of codeigniter and in a new migration, I create the database with dbforge like so $this->dbforge->create_database('website_store'). So far so good, then I connect to this database using $DB2 = $this->load->database('store', TRUE); and create a table. All is good here as well.
Then the migration ends and codeigniter tries to update the migration table to push the latest version, but looks into the store database instead of the default database, so it pops this error:
Table 'website_store.migrations' doesn't exist
UPDATE `migrations` SET `version` = 45
Hopefully someone knows about using multiple database and the migration library. By the way, in the database.php file, it is set to use the default database: $active_group = "default";, not the store database so it should work. It looks like the migration library sees that there is already a database loaded, feels lazy and uses that one instead.
NOTE:
Looks like these guys had similar problems that they fixed by setting 'pconnect' to 'false', but it would be nice to keep a connection to both database:
Convenient Way to Load Multiple Databases in Code Igniter
Error Using Multiple Database In CodeIgniter
In CI i have dealt with multiple databases using:
function readFromOtherDB(){
$config = array(
'hostname' => "XXX",
'username' => "XXX",
'password' => "XXX",
'database' => "XXX",
'dbdriver' => "mysql",
'dbprefix' => "",
'pconnect' => FALSE,
'db_debug' => TRUE,
'cache_on' => FALSE,
'cachedir' => "",
'char_set' => "utf8",
'dbcollat' => "utf8_general_ci"
);
$otherDb = $this->ci->load->database($config, true);
$query = $otherDb->get_where('users', array('email' => $_email));
$otherDb->close();
}
I have a Laravel 4 db:seed file that I am trying to use on mediatemple gridserver. I was able to run a migration with artisan fine (php artisan migrate), and make the tables, but I am not able to seed the tables. This database seeding worked fine on local host. It is only now on a live server that I am experiencing any issues with it. Here is the seed file:
ArtistsTableSeeder.php:
class ArtistsTableSeeder extends Seeder {
public function run()
{
// Uncomment the below to wipe the table clean before populating
// DB::table('artists')->delete();
$artists = array(
);
$Artists = [
['stage_name' => 'Blah', 'city' => 'Blah', 'state' => 'blah', 'video_path' => 'youtube.com', 'image_path' => 'filepickerimage', 'soundcloud_profile' => 'https://soundcloud.com/', 'description' => '', 'created_at' => new DateTime, 'updated_at' => new DateTime]
];
// Uncomment the below to run the seeder
DB::table('artists')->insert($Artists);
}
}
It is spitting out this error:
{"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","message":"syntax error, unexpected '['","file":"\/nfs\/c09\/h04\/mnt\/139243\/domains\/crowdsets.com\/html\/app\/database\/seeds\/ArtistsTableSeeder.php","linemichaelsutyak.com#n26:/home/139243/domains/crowdsets.com/html$ php artisan db:seed
It is complaining about the line that starts the array:
$Artists = [
I have no idea why this is happening. A little help would be appreciated. Thank you!
That syntax error you get is probably caused by a feature that has been added in PHP 5.4 (short array syntax), so I'd guess your hoster still runs 5.3.x.
You should check the PHP version on the mediatemple grid server and update it if necessary.