Laravel 4 - Connect to other database - php

I want to connect to another database sometimes.
I created a config.php with the database connection data.
But how can i tell laravel to connect to this database insted of using the config/database.php?
For example when using the Schema class.
Since no one seems to understand what i want.
I DON'T want to use the config/database.php, i want to use a different config file on a different location.

It sounds like you figured this out. Here's how I'd accomplish it anyway for other people coming in, or in case something useful is here for you.
First, Add a second connection in app/config/database.php. Note: That file path may change depending on your environment.
<?php
return array(
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
'mysql2' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
Second, in your code, you can use (as mentioned) the 2nd connection where you would like:
Schema::connection('mysql2')->create('users', function($table) {})
There's more documentation on this - see Accessing Connections.
Eloquent ORM
You can define the variable for "connection" in an eloquent class to set which connection is used. That's noted in the Basic Usage section.
See that variable on here on Github and the method which you can set to set the connection dynamically here.
Edit
The OP has made it clear that they do not wish to use the config/database.php file for config.
However without explaining further, I can't comment. I'm happy to help - sounds like it would be useful to know why the config/database.php file can't/shouldn't be used, as this can help us ascertain the problem and create a useful solution.

I believe you want to implement some kind of logical sharding where databases would be dynamically created.
In such scenario in laravel you can dynamically add a database config, like below
$conn = array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'DATABASE',
'username' => 'USERNAME',
'password' => 'SOME_PASSWORD',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
);
Config::set('database.connections.DB_CONFIG_NAME', $conn);
Now to connect via eloquent
MODEL::on('DB_CONFIG_NAME')->WHAT_EVER('1');
Incase of Query Builder you can do
$DB = DB::connection('DB_CONFIG_NAME');
use $DB->select() for querying now.
Hope this would help devs looking for a possible solution for this question

Remember that Laravel 4 is actually a collection of components, and you can use these components solo.
https://github.com/illuminate/database
There is an example here that shows off how interacting with the Capsule class works:
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Set the cache manager instance used by connections... (optional)
$capsule->setCacheManager(...);
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();
This is a bunch of bootstrapping that you'll need to run, so tuck it away somewhere in a function or method.
But, its absolutely possible.

There is a simpler solution. If you are using Larave 4 there is an option that worked for me. Recently they added $table variable that you can specify in your model. Refer to this link.
class User extends Eloquent {
protected $table = 'my_users';
}
If you are using MySQL, you can do the following:
class User extends Eloquent {
protected $table = 'mydbname.my_users';
}
If you are using SQL Server, you can do this:
class User extends Eloquent {
protected $table = 'mydatabase..my_users';
}
My Config file had DB1 specified but I created a model which wants to access DB2 in the same MySQL host. So this was a quick and dirty way to accomplish this.
Now I don't fully leverage Eloquent ORM all the time so this "hack" may not work with Many to Many or one to Many Eloquent methods.
One another idea I had but I didn't actually try was creating a stored procedure (routine) in DB1 and inside of that routine I can access DB2 tables by querying link this:
SELECT * from db2.mytable where id = 1;

To use a config file in another location, say src/config:
use Config;
$this->dbConfig = Config::get('appname::dbInfo.connections.test');
$this->database = $this->dbConfig['database'];
$this->username= $this->dbConfig['username'];
$this->password= $this->dbConfig['password'];
Where dbInfo is a simple php file in your app's src/config directory returning an array containing the element connections which is an array of database properties.
You can tell Laravel to use an external config file using:
Config::set("database.connections.test", $this->dbConfig);
DB::connection("test");

Edit bootstrap/start.php file and add your machine name (open terminal: hostname).
Add your machine to $env,
$env = $app->detectEnvironment(array(
'mymachine' => array('mymachine.local'),
));
Create a new path at 'app/config/mymachine'
Add a copy of database.php with new config params.

Related

Possible to Dynamically Connect to Postgres DB from Laravel without using Config ? See Example

I have a situation where I'd like to dynamically choose the DB host for postgres DB connections in a Laravel application running in Docker. I don't particularly want to use ENV values or the config/database.php file because it is a one-off query to the external DB that I would prefer to embed in Helper Class.
These actually could go in the .env file:
PSQL_DB_PORT=5432
PSQL_DB_DATABASE=postgres
PSQL_DB_USERNAME=postgres
PSQL_DB_PASSWORD=postgres
and in my helper I can get the hostname for the remote (actually in Docker) postgres server, which will basically be something like:
postgres_index-db1, postgres_index-db2, postgres_index-db3, etc., but I need to fetch that dynamically and store it in a variable $host.
I tried playing around with a thing like this:
DB::disconnect('pgsql');
Config::set("database.connections.pgsql", [
'driver' => 'pgsql',
'host' => $host ,
'port' => env('PSQL_DB_PORT', '5432'),
'database' => env('PSQL_DB_DATABASE'),
'username' => env('PSQL_DB_USERNAME'),
'password' => env('PSQL_DB_PASSWORD'),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
]);
dd(DB::connection('pgsql'));
$query = "select DISTINCT value from maindicomtags where taggroup = 8 and tagelement = 128";
$names = DB::connection('pgsql')->select($query,[]);
and the dd(DB::connection('psql')) (a Laravel dump) statement actually shows the correct config, but when the query tries to execute it must be looking for the pgsql config in my config/database.php file because it throws an error:
Database connection [pgsql] not configured
because it must be looking for the config in the config/database.php file, and I removed the definition from there. I want it to use the connection that is defined above.
Is there a a way to do what I am trying to do. I could even just use the connection string for Postgres if that is possible.
Might actually be working because I might have had a typo earlier (e.g. psql vsl pgsql).
Does this seem like an adequate way to make that type of dynamic connection ? It is really just the host that will be different.
Instead of setting your config, just create a custom database connection using factory. The only downside - you will not be able to use Eloquent as it resolves connection by its name defined in configs. Also, avoid using env variables anywhere else than config files - create other config and use it instead. There is quite a chance something could break somewhere else if you change config on the go:
$factory = app(\Illuminate\Database\Connectors\ConnectionFactory::class);
$db = $factory->make([
'driver' => 'pgsql',
'host' => $host ,
'port' => $port ?? 5432,
'database' => $database,
'username' => $username,
'password' => $password,
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
]);
$names = $db->table('maindicomtags')
->where('taggroup', 8)
->where('tagelement', 128)
->distinct()
->pluck('value');
$db->disconnect();

Laravel 5.6 change database connection in the runtime permanently

I have two databases. The second database changes dynamically, i.e. each client has its own database so the database name and password are different but the architecture is the same for all clients. So I have two model groups, the first for the first database and the second for the second database. Indeed, the second model group must be able to make queries to the client database and not to the default database
so I want to set the default database connection dynamically.Config::Set() will do it for one request only. I want it for every subsequent request.
I use the Laravel Framework, you know of a clean solution that might solve my problem and help others interested
thanks to everyone for your help
Create two entries in config/database.php:
'connections' => array(
# Connection one
'mysql_1' => array(
'driver' => 'mysql_1',
'host' => 'host_1',
'database' => 'db_1',
'username' => 'username_1',
'password' => 'password_1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
# Connection two
'mysql_2' => array(
'driver' => 'mysql_2',
'host' => 'host_2',
'database' => 'db_2',
'username' => 'username_2',
'password' => 'password_2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
Create a base model or a Trait for each group of models which sets the connection at the model level. Change all your models to extends from their respective base model.
Base Models
class BaseGroupOneModel extends Model
{
protected $connection = 'mysql_1';
}
class BaseGroupTwoModel extends Model
{
protected $connection = 'mysql_2';
}
Traits
trait GroupOneTrait
{
protected $connection = 'mysql_1';
}
trait GroupTwoTrait
{
protected $connection = 'mysql_2';
}
class GroupOneModel extends Model
{
use app/Models/Traits/GroupOneTrait;
}
class GroupTwoModel extends Model
{
use app/Models/Traits/GroupTwoTrait;
}

Dynamically change database connection in cakephp 3

I'm trying to change the database connection used in cakephp 3 on the fly. Every answer to this question that I found refers to cakephp 2 (These three for instance).
This guy found a solution for cakephp 3 having a finite number of databases, and specifically defining which Database would be used by which Table file.
The thing is that I want to create a new database for every new user, and change to his database when he logs in. I can't know in advance all the databases that will exist, to write it in the config/app.php file.
And I can't set the default database in each /src/Model/Table file, because the tables are the same in every database.
Use the ConnectionManager::config() function to create connections on the fly and the ConnnectionManager::alias() method to make all your Table classes use it by default.
There is a very good article describing the process here:
http://mark-story.com/posts/view/using-cakephp-and-a-horizontally-sharded-database
The only difference is that you can create the connection config on the fly instead of declaring the shards manually as it was shown in that article.
Change database connection for one model:
In app.php :
'test' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => MySQL_HOST,
//'port' => 'nonstandard_port_number',
'port' => MySQL_PORT,
'username' => MySQL_USER,
'password' => MySQL_PASS,
'database' => 'test',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
]
In Controller :
$conn = ConnectionManager::get('test');
$_model = TableRegistry::get('your_alias', ['table' => 'your_table', 'connection' => $conn]);
Configuring table connections
namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
{
public static function defaultConnectionName() {
return 'replica_db';
}
}

Laravel 4.2 dynamic database connection

I am trying to setup connections to multiple database under the same instance for correlation data analysis
Here is the basic idea of the connection code
$a = array('a','b','c');
$b = array('a','b','c');
foreach($a as $ac){
foreach($b as $bc){
Config::set('database.connections.'.$ac.'_'.$bc, array(
'driver' => 'mysql',
'host' => 'somehost',
'port' => '3306',
'database' => $ac.'_'.$bc,
'username' => 'user',
'password' => 'user',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''
));
}
}
There are about 40 different db in that instance, and could change rapidly, so I want to avoid permanently create the connection in the config file and generate the connection on the fly with user input. And from what I gather, the above code should auto append the array to database.connections (see laravel github ), but I am getting this error.
SQLSTATE[HY000] [2002] No such file or directory
if I change database.connections.".$ac.'_'.$bc to database.connections.mysql the code runs okay. So what am I missing here :( , I am calling that piece of code under the constructor of the first controller the input will hit.
Thank you very much for the help in advance
After playing around a bit, found out what's the problem.
After calling the code above in controller,
in model, not only you have to make the initial connection but also you have to include a table in that statement in order to divert the connection to the specific DB, otherwise it will fall back to default connection if you use the way that builder query example from Laravel documentation. So instead of doing
$this->query = DB::connection($ac.'_'.$bc);
$this->query = DB::table('sometable');
do it like
$this->query = DB:connection($ac.'_'.$bc)->table('sometable');
Then connection for $this->query will lock to the new database pointed.

Laravel php script DB class not found

I'm trying to write a script for laravel that queries
my database and fetches tables, but I'm not sure what to include
in the file in order to get the DB class to work.
Thus far my code looks like:
$tables = DB::query("SHOW TABLES");
foreach ($tables as $table) {
print $table . "\n";
}
I've tried using require "../../vendor/autoload.php" but that doesn't help.
So for instance, the DB class works fine if I call it within a controller, but not
if I create a directory, say /application/scripts and create a file test.php .
If I try to call DB in that file, the DB class isn't defined (for good reason).
I'm wondering what I need to require in that file in order for that class to be defined.
I would suggest using the Illuminate/Database package (part of Laravel 4). You won't get the DB interface, because that's a special facade provided by the Laravel Framework, but all the query builder functionality is available through the capsule.
Install illuminate/database using composer and then follow the included readme notes (included below for completeness).
Illuminate Database
Usage Outside Of Laravel 4
$config = array(
'fetch' => PDO::FETCH_CLASS,
'default' => 'mysql',
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'laravel',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
$capsule = new Illuminate\Database\Capsule($config);
// If you want to use the Eloquent ORM...
$capsule->bootEloquent();
// Making A Query Builder Call...
$capsule->connection()->table('users')->where('id', 1)->first();
// Making A Schema Builder Call...
$capsule->connection()->schema()->create('users', function($t)
{
$t->increments('id');
$t->string('email');
$t->timestamps();
});
You do not need to include anything. Laravel will include what it needs and setup the system itself. You are using a variable called $db but it is not defined and means/does nothing. What you are looking for is the DB class. Try this:
$tables = DB::query('SHOW TABLES');
foreach ($tables as $table)
{
echo $table.PHP_EOL;
}
Also, check out the Fluent DB class documentation:
http://laravel.com/docs/database/fluent
...Isn't it DB::query()? A call to the database engine is through a class, not a variable, for scoping issues.

Categories