Zend_Db using multiple databases? - mysql

Is there a way I can use Zend_Db to make updates and insert crossing multiple (two) databases?
Example,
UPDATE database1.tableA AS a1, databse2.tableA as a2 SET a1.content = a2.content WHERE a1.id = a2.id
How could I do this with Zend_Db_Adapter_Pdo_Mysql?

I have multiple databases defined in my application.ini file
I have used something like this:
// REGISTRY
Zend_Registry::set('configuration', $configuration);
foreach($configuration->database as $type => $database){
$db[$type] = Zend_Db::factory(
$database
);
}
Zend_Registry::set('db', $db);
Upon creating your model you specify which db you want in the models constructor
$newModel = Model_NewModel($db['db_key_name']);
You then have 3 options, you can either manually code your own object to extend Zend_Db_Table_Abstract and have a multi-db-update function
/* the code for this example is pseudo code, so it probably wont work but the concept is still good */
class Model_NewModel extends MoakCustomDbClass{
function multi_db_update($db1, $db2, $update, $where)
{
$originalDb = $this->_db;
$this->_db = $db1;
$this->update($update, $where);
$this->_db = $db2;
$this->update($update, $where);
$this->_db = $originalDb;
}
}
, write your own custom query by calling
$newModel->query('UPDATE QUERY');
or running 2 models both pointing at different databases
$newModelA = Model_NewModel($db['db_key_name_A']);
$newModelB = Model_NewModel($db['db_key_name_B']);

Related

How to save laravel model to 2 databases

Hi is there a way to do something like:
$model->name = 'newname'
$model -> save()
Change database connection
$model save()
Change back.
I know you can do it with manual queries
DB::Conection(conectio1)->update($SQLString)
DB:Coneection(conection2)->update($SQLString)
MYSQL replication is not instant
thnx in advance
I have actually never tried that but it should be possible using the setConnection() method of your model.
$model->setConnection('connection2');
But you will have to replicate the model before you change anything on the original model instance because otherwise it won't recognise changes of the same attributes with the same values anymore (if they don't differ from the values you used before).
$model2 = $model
->replicate()
->setConnection('connection2');
$model->name = 'name';
$model->save();
// You need the replicated model here because if you used the same model
// with a different connection the model can not say that `name` has changed
// because the value hasn't changed.
$model2->name = 'name';
$model2->save();
I found the easiest way.
public function saveMultipleDatabases($db)
{
Config::set('database.default', $db);
$model->name = 'newname'
$model->save()
}

Need to change timezone dynamically for existing project

There is an existing project only for one country. But for now, it should be used for multiple countries. So I need some place to change timezones. I decided to update & insert in only London/Sydney timezone. I need to change the timezone for all select queries. I just tried with middlewares, but I could not achieve it. Please give your suggestions.
Linux server, MySQL, Laravel, Vagrant
namespace App\Http\v2018_06_12\Middleware;
use App;
use App\Order;
use Closure;
class LocaleMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
$locale = ($request->hasHeader('locale')) ? $request->header('locale') : 'uk';
$timezone = env('APP_TIMEZONE');
if ('aus' == $locale) {
$timezone = 'Australia/Sydney';
}
config(['app.timezone' => $timezone]);
date_default_timezone_set($timezone);
print_r(Order::select('delivery_time')->orderBy('id', 'DESC')->first()->toArray());
return $next($request);
}
}

How to write this raw query using query builder? Is my one correct?

This is the expected result of raw query
$sql = 'SELECT c.*
FROM catalogs c
LEFT JOIN (SELECT s.* FROM stock s WHERE s.date = "'.$dateOption.'") as sb
on sb.id_product = c.id_product
WHERE c.id_branch = '.Auth::user()->id_branch.';
$list = DB::select($sql);
I modified it using query builder, but the result is not correct
$lists = DB::table('catalogs')
->leftJoin('stock', 's.id_product','=','catalogs.id_product')
->where('s.date',$dateOption)
->where('catalogs.id_branch',Auth::user()->id_branch)
->get();
Anyone can tell me how should i write it in query builder?
Defining Relationships (more details)
The first argument passed to the hasOne method is the name of the related model. Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
And then you can get the join like bellow.
$phone = User::find(1)->phone;

Symfony2 execute SQL file in Doctrine Fixtures Load

I'm migrating an old web app based on SQL Server and ASP to Symfony2 and MySQL. I made some queries and export old data to individual SQL files.
How can I execute thoses files in my fixtures, when I run the command
$php app/console doctrine:fixtures:load
Now I have some fixtures that works directly with Doctrine ORM and entities, but I have a lot of data to import.
I find a good solution. I didn't find an exec method in class ObjectManager, so... this work very well for me.
public function load(ObjectManager $manager)
{
// Bundle to manage file and directories
$finder = new Finder();
$finder->in('web/sql');
$finder->name('categories.sql');
foreach( $finder as $file ){
$content = $file->getContents();
$stmt = $this->container->get('doctrine.orm.entity_manager')->getConnection()->prepare($content);
$stmt->execute();
}
}
In this solution your fixture class has to implement the ContainerAwareInterface with the method
public function setContainer( ContainerInterface $container = null )
{
$this->container = $container;
}
You can load the file contents as a string, and execute native SQL using the EntityManager:
class SQLFixtures extends AbstractFixture implements OrderedFixtureInterface
{
$filename = '/path/to/sql/file.sql';
public function load(ObjectManager $manager) {
$sql = file_get_contents($filename); // Read file contents
$manager->getConnection()->exec($sql); // Execute native SQL
$manager->flush();
}
public function getOrder() {
return 99; // Order in which this fixture will be executed
}
}
Answer for Zend Framework 2.5.3 using Doctrine Data-Fixtures.
Not sure if this applies to the given answers, but they are trying a bit too hard. If you inspect the given $manager object, you'll find that it already is the EntityManager (of interface ObjectManager) (at least, in ZF2). As such you're able to get the Connection directly and it's possible to execute without using $this->container->get('doctrine.orm.entity_manager')
Below a snippet which I use for creating the first user "system", with a createdBy FK reference to itself.
public function load(ObjectManager $manager)
{
$sql = 'INSERT INTO users (
id, username, email, display_name, `password`, created_by)
VALUES (:id, :username, :email, :display_name, :password, :created_by)';
$password = $this->createSuperDuperEncryptedPassword();
// $manager === `EntityManager|ObjectManager`, `->getConnection()` is available
$stmt = $manager->getConnection()->prepare($sql);
$stmt->bindValue(':id', 1);
$stmt->bindValue(':username', 'system');
$stmt->bindValue(':email', 'system#system.test');
$stmt->bindValue(':display_name', 'system');
$stmt->bindValue(':password', password );
$stmt->bindValue(':created_by', 1); // Self reference
$stmt->execute();
}

Use existing MySQL database in CodeIgniter

In my PHP websites I’m using SiteTranslator script for a website translated into 30 languages. Each translation is stored in its own table (text_en, text_de...) and each table has 3 columns (textKey, textValue, lastUpdate).
Now I would like to use that database in my CodeIgniter application.
What would be the best way to do it?
You could use multiple databases as suggested, you would still need to setup your app language files
{read more in the user guide}
Based on the first uri segment you could try something like this.
Adding routes
$route['en|fr|gr/test'] = 'test';
First segment checks for en OR fr OR whatever else.
Then the Main Controller catches the first segment before the test controller is initialized and the db(object) && app(language) files are set
www.site.com/en/test => load english language file(application/language/english/mylanguage) and db
www.site.com/fr/test => load french language file(application/language/french/mylanguage) and db ...and so on
Main Controller
class MY_Controller extends CI_Controller{
protected $lang, $db;
public function __construct(){
parent::__construct();
$this->set_language();
}
protected function set_language(){
switch($this->uri->segment(1))
{
case 'en':
$this->lang = $this->lang->load('mylanguage', 'english');
$this->db = $this->load->database('en', TRUE);
break;
case 'fr':
$this->lang = $this->lang->load('mylanguage', 'french');
$this->db = $this->load->database('fr', TRUE);
break;
default:
$this->lang = $this->lang->load('mylanguage', 'english');
$this->db = $this->load->database('en', TRUE);
break;
}
}
}