Laravel - Change Database Connection for a specific URL? - php

I am fairly new to using laravel framework. I have the following requirement. I have a domain - example.com, and its entire code stack is running in laravel. Lets say in the config default database connection is - 'db1'
Now, if the url becomes - example.com/country - I want the default database connection to become - 'db2'
And also I want the base URL to be changed to example.com/country, since all the modules are going to be the same. Only the database connection is going to change here.
Could someone help me out here?

I would do it the following way:
Put the list of allowed countries into config file (countries.php) .
In routes.php:
// choosing country
$country = '';
if (in_array(Request::segment(1), Config::get('countries'))) {
$country = Request::segment(1);
}
// making route for top level
if ($country != '') {
Route::any( '/', 'MainPage#index');
}
// making routes optionally prefixed by country
Route::group(
array('prefix' => $country,
function () {
// here all routes
});
In database.php where you have defined your connection you could add another connections for example:
'germany' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'germany_connection',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
Now in the same file (although you should probably move it somewhere else) you can do:
if ($country == 'germany') {
DB::disconnect();
Config::set('database.default','germany');
DB::reconnect();
}
You can of course add many conditions here or if you have defined connection for each allowed country you can simply do:
if ($country != '' ) {
DB::disconnect();
Config::set('database.default', $country);
DB::reconnect();
}
It should work however I haven't tested it

I've made something similar using environments.
Add a new rule when detecting the environment to parse the URL and change it to the new environment. Then you can add a directory for the new environment where you set up the new database, base URL, etc.

Related

laravel 5.4 dynamic database connection

I am building the admission portal in laravel,
I have super admin database which has a schools table with 100 rows,
schools table structure
1.id
2.school_name
3.database details
I want to connect to the school database with its database details by its id.
technically
1.I will pass the school id from url
2.it will select that row from school table
3.after selecting the database details of particular school
4.will connect to the school database for further use.
I went through https://laracasts.com/discuss/channels/tips/set-up-dynamic-database-connection-globally
http://fideloper.com/laravel-multiple-database-connections
but no luck
please help to sort it out.
Actually you dont want multiple connections, but rather change existing connection.
public function setSchoolConnection($id) {
$school = School::find($id);
if ( $school ) {
config(['database.mysql' => [
'database' => $school->database,
'username' => $school->username,
'password' => $school->password
]]);
}
}
Now the default connection has been changed. I think.
If you don't want to change existing connection, just create a new connectio
config(['database.school' => [
'driver' => 'mysql',
'database' => $school->database,
'username' => $school->username,
'password' => $school->password
]]);
and use it like this
$users = DB::connection('school')->select(...);
Have you tried setting the connection in the School model? Laravel will take care of the rest, even if you have relations with different connection.
In your School model, I will override the constructor like so:
public function __construct(array $attributes = [])
{
$this->setConnection(env('DB_SCHOOL_CONNECTION'));
parent::__construct($attributes);
}
The one thing to be careful of is if you have a relation with a different connection, using whereHas or has in your query/builder wont work. as laravel will not be able to set the connection in the query generated.

Disable or bypassing name conventions in cakePHP3

I have following Data:
Database name = ThisDatabase
Table name = InfoData
cakePHP3 convert the names in
ThisDatabase = this_database
InfoData = info_data
My problem is that I have no chance to rename the DB or Table names so I have to disable or bypass the name converting in cakePHP3.
But I have no clue how I can do this.
How can i disable the converting? So I can use the actual names (ThisDatabase and InfoData).
You should follow naming convention for your files and cakephp to work properly, and specify the table name in initialize function inside your App\Model\Table\ArticlesTable.php
Here you can find related documentation
That's easy, CakePHP offers you a way to change the name of the table as you wish.
For the database, in the app config, set the database name :
...
'Datasources' => [
'default' => [
...
'username' => 'username',
'password' => 'password',
'database' => 'ThisDatabase', // Here you can set the database name
'encoding' => 'utf8',
..
]
],
...
Here is some doc
For the table name : In your table definition, change the table name
class Infodata extends Table
{
public function initialize(array $config)
{
$this->table('InfoData');
}
}
Here is is the doc

How to change the database connection in YII

I have yii application,, and i want to change the database connection..
first, my app is connect to 'trackstar' database, and later i want to change to 'taskmanagement' database..
So i just simply change the dbname in my code :
<?php
// This is the configuration for yiic console application.
// Any writable CConsoleApplication properties can be configured here.
return array(
'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
'name'=>'My Console Application',
// application components
'components'=>array(
'db'=>array(
'connectionString' => 'mysql:host=localhost;dbname=taskmanagement',
'emulatePrepare' => true,
'username' => 'root',
'password' => '',
'charset' => 'utf8',
),
'authManager'=>array(
'class'=>'CDbAuthManager',
'connectionID'=>'db',
'itemTable' => 'tbl_auth_item',
'itemChildTable' => 'tbl_auth_item_child',
'assignmentTable' => 'tbl_auth_assignment',
),
),
);
but when i run the app i got error :
CDbCommand failed to execute the SQL statement: SQLSTATE[42S02]: Base
table or view not found: 1146 Table 'trackstar.tbl_auth_assignment'
doesn't exist. The SQL statement executed was: SELECT * FROM
tbl_auth_assignment
WHERE userid=:userid
the thing i dont understand is that why is still connect to trackstar database eventhough i just change the dbname to taskmanagement
thx before :)
I guess one your model queries written as straight SQL query.
EX:
SELECT * FROM databaseName.tableName
So, Even you change the database name in the config file these kinds of queries may not work. Please check your code in this way.
You are only configure the console.php Configuration . But Yii Web application use the main.php
Check your main.php file
its located on Your App folder -> Protected -> config ->main.php
Change Db connection on this file
You can use below code to update database dynamically
if ($city == 'ABC') {
$databse = 'db_abc';
} elseif ($city == 'BCD') {
$databse = 'db_bcd';
} else {
$databse = 'default_db';
}
$db = Yii::$app->getDb();
$db->dsn = "mysql:host=localhost;dbname=$databse";
Hope this help to override database connection string

PHP Yii: Database connect in runtime

I would like to connect to a second database with Yii at runtime. The database name would come from a database table after the user to login.
I saw in a tutorial I should do this:
$db2 = Yii::createComponent(array(
'class' => 'EMongoClient',
'server' => 'mongodb://127.0.0.1:27017',
'db' => $emp['database']
));
Yii::app()->setComponent('db2',$db2);
But in my controler when I access Yii::app()->db2 get the error:
Property "CWebApplication.db2" is not defined
What am I doing wrong?
The following works for me:
Yii::app()->mongodb->setActive(false);
Yii::app()->mongodb->setServer('mongodb://localhost:27017');
Yii::app()->mongodb->setDb('db1');
Yii::app()->mongodb->setActive(true);
UPDATED: Try, instead instance, pass configurations:
Yii::app()->setComponent( 'db2', array(
'class' => 'EMongoClient',
'server' => 'mongodb://127.0.0.1:27017',
'db' => $emp['database']
)
);
Or, you may create special index on params in configurations, such as:
...
'params' => array(
'db2' => null,
),
And the use Yii::app()->params['db2'] = $db2
From this comment:
My problem is not with the creation of the component. Soon after
creating if I access Yii::app()->db2 its works, but when I try to
access via another model or controller I get the error
I think you are setting this component only once somewhere, and then making subsequent requests to different controllers.
You need to put the code, somewhere it is being called EVERYTIME, on every Request. thats how PHP works, there is no "global application state"
by default Yii comes with protected/components/controller.php has base controller for the rest of the app.
my suggestion would be to put your code on the init() method of that controller, so that it always gets called.
You mentioned the database name comes from a table once the user logs in, so you need to save that value in the session, in other to be able to access it in the other requests:
<?php
// After login in
Yii::app()->user->setState('db_name', $db_name);
// in protected/components/controller.php
public function init()
{
if (!Yii::app()->user->isGuest) {
$db2 = Yii::createComponent(array(
'class' => 'EMongoClient',
'server' => 'mongodb://127.0.0.1:27017',
'db' => Yii::app()->user->getState('db_name')
));
Yii::app()->setComponent('db2',$db2);
}
}
Hope it helps, I am assuming many things here :)

What are the step you have to go through when updating an application to be multilingual?

I need to update an application which is built on Zend Framework.
Most of the text is hard-coded in views scripts, forms, etc.
The application will be available in say, 3 languages AND is language specific (the content is not the same for all) and will have one domain per language (ie: mygreatsite.com, monsupersite.com, ilmiosupersite.com, etc.)
First question:
What is the best way to "handle" this kind of application?
I can imagine several solution like:
One copy per language, using different db, etc... (probably not the best way for maintenance)
Only one application, handling different content, db, etc, depending on the locale (based on the route)
Second question:
What should I need to know about the existing code to start the "migration"?
What about any best practice when building a i18n website?
What are the best adapter? (I already used gettext() and I think it's the best)
I am by no means an expert but this is what I do.
I use array as my translation adapter because it’s easier for my clients to update as they are just regular Joes. And I use translation keys instead of sentences. For example
Some people would use
$this->translate(‘Some sentence to translate’);
I use
$this->translate(‘default-index-dashboard-title’);
This makes it far easier for me to know where the text I’m looking for is to change. I don’t know if there are any advantages other than that though.
You will need to setup your translation adapter and translation cache (if you want) in your bootstrap. I do mine like this:
protected function _initLocale()
{
$locale = new Zend_Locale(Zend_Locale::BROWSER);
$config = Zend_Registry::get('config');
Zend_Registry::set('Zend_Locale', $locale->toString());
return $locale;
}
protected function _initTranslation()
{
try{
$translate = new Zend_Translate(array('adapter' => 'array', 'content' => ROOT . '/callmanagement/languages/' . strtolower(Zend_Registry::get('Zend_Locale')) . '.php'));
}catch(Exception $e){
$translate = new Zend_Translate(array('adapter' => 'array', 'content' => ROOT . '/callmanagement/languages/en_gb.php'));
}
Zend_Registry::set('Zend_Translate', $translate);
return $translate;
}
I would use a single code base unless the sites are completely different and store the shared data in one database and have other databases for the site specific stuff.
You can setup multiple db adapters either in the bootstrap or in the congfig.
$dbLocal = new Zend_Db_Adapter_Pdo_Mysql(array(
'host' => 'localhost',
'username' => $result['user'],
'password' => $result['password'],
'dbname' => $result['database']
));
Zend_Db_Table_Abstract::setDefaultAdapter($dbLocal);
$dbShared = new Zend_Db_Adapter_Pdo_Mysql(array(
'host' => 'localhost',
'username' => ‘root’,
'password' => 'pass',
'dbname' => 'dbname'
));
Zend_Registry::set('db_local', $dbLocal);
Zend_Registry::set('db_shared', $dbShared);
return $dbLocal;
You can get Zend Form to translate for you just put your translation key into the label field.
$this->addElement(‘text’, ‘test’, array(‘label’ => ‘translation-key’, ‘required’ => true)); etc.
Then if you are using Zend_Db_Table_Abstract classes you can change the default schema and database connection like this:
class Default_Model_Table_Topics extends Zend_Db_Table_Abstract
{
protected $_name = 'topics';
protected $_id = 'topic_id';
protected $_rowClass = 'Default_Model_Topic';
protected $_schema = 'dbname';
protected $_adapter = 'db_shared';
}
If you need any more examples I’ll try and help.

Categories