I have no idea how to google this since I mostly get tutorials about setting up multiple database connections.
At the moment, completely at random, my Laravel application gives me back an error about SQL, that the table could not be found. Laravel connects in this case to an entitely different database for some reason.
I connect in my .env and config/database.php to database1. Suddenly, an SQL error appears reading
Cannot find table `database2`.`table` in field list.
User also gets logged out when this error occurs.
Might be of use if i include that:
I sometimes use a custom user provider and sometimes the Laravel user provider. It depends on the subdomain. Error occurs on both configurations.
I dynamically add other database connections to the config, but never one to "database2". Database2 is a completely different application.
A search through the source code does not find any match with "database2"
Has anyone come across this problem? And if yes, how do I solve this? Thanks in advance!
Basically any Laravel Eloquent Model at seemingly Random will behave as if it was set with the public $connection="database 2"; variable.
Have you defined a model to use a different connection maybe?
Following the Laravel docs, this lets you use a different connection for specific models.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* #var string
*/
protected $connection = 'connection-name';
}
One of the most common reason is because you are setting your Configuration in a dynamic way with variables, so the Cache gets cached with the wrong information in this case the default database connection.
Or you could be setting the configuration at runtime which also makes the Illuminate\Foundation\Console\ConfigCacheCommand.php to generate the wrong files.
Make sure your configurations are serializable. Try running the command.
php artisan cache:config
Related
the background for this is that we have an existing site which is going to be somewhat linked with the new one, so it would make a lot of sense to use the same user base.
So, we want to use the same user database. The way I tried is not working, adding two databases and providing the same Entity. This is also a different Symfony project, I could do it on the same one but it's more convenient to separate it because it might be running on different servers later on.
How can I make my user provider fetch the users from another MySQL database the easiest or best reliable way?
Have you looked at the documentation for using multiple entity managers?
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
You can set up configuration for multiple database connections and define which connection to use by default based on the bundle.
Alternatively you can explicitly choose which connection to use with
$this->get('doctrine')->getManager('<your custom manager name>');
If you're using a user provider specified in your security.yml (the approach used here) you can inject the userRepository for your alternate connection in the service definition.
your.definition.of.user.provider:
class: YourBundle\Entity\UserProvider
arguments:
- #=service('doctrine').getRepository('YourBundle:User', '<alternate manager name goes here>')
Background:
I have an admin system, that needs to connect to and edit multiple databases. The database structures are 100% similar to each other, but the data varies.
What I have tried:
I'v tried to use $this->Model->setDataSource('db_variable_here'); in the controllers to change the database on the fly. The problem with this, is that all the related data seems to still be from my default database.
Example:
Imagine this: User HABTM Post, if I want to get a post from a different database, and use $this->Post->setDataSource('db_variable_here'); to achieve this, then it seems that I still get the related user from my default database, and not the same as the one I got the post from.
I'm guessing this is due to the fact that I only change the database on the Model Post, so it could be fixed by doing $this->Model->setDataSource('db_variable_here'); for each related model.
My Question:
Is it possible to change the datasource for every model in the app on the fly?
Ex. something like: $this->setDatasource('datasource_name')? Or do I really have to do it manually for all the related models?
Just save the database that you need to use in Session/Cookie (whatever tickles your fancy), then in your AppModel's __constructor() if the Session variable is defined then override either setDataSource() or setSource() accordingly.
Note that IIRC Cake's Session/Cookie are not available on the Models by default (because it's not supposed to be), so you might wanna use the good ol' $_SESSION or $_COOKIE or you will need to load it with App.
I do this to select to either use a Azure SQL database or a Rackspace MySQL database depending on the domain/URL, works as expected.
You could try making your own getDataSouce method in the AppModel.
You can see the CakePHP one here:
https://github.com/cakephp/cakephp/blob/master/lib/Cake/Model/ConnectionManager.php
So, in your AppModel, just make sure to accept/return the da
class AppModel extends Model {
//...
public function getDataSource() {
// some logic here to determine which source you want
// Maybe use Configure::write('MYSOURCE', 'other_datasource');
// somewhere else, then just check it here.
$source = 'default';
$this->setDataSource($source);
return parent::getDataSource();
}
//...
}
This should get called instead of CakePHP's 'getDataSource()', then it will run your checks to determine which connection to use, then calls CakePHP's 'getDataSouce()' to do the rest of the actual work of getting the data source.
Assuming you set a variable (like a Configure variable) that's accessible from here, you could set it once anywhere in the app, and when this runs, it will use whatever you've specified.
I have a simple question but I haven't found an answer in the web. Maybe my keywords are false.
So I am developing an app in Laravel 4. And I need to seed the database with different values according to the current active environment.
So for example, if I am on the local environment, I want to have test data and so on. But when I am on the production environment I only want to have an admin user.
Does Laravel has an built in solution for that?
If not, how can check, which environment is active in the app/seeds/DatabaseSeeder.php file. So I can call different seeder according to the environment.
There's no built-in handler for different environments in the manner you would like.
Solution
Within the seeder class, you should be able to use App::environment() to detect the environment, and do logic based on that.
You can add that within each table seeder class, or within the DatabaseSeeder.php file:
public function run()
{
Eloquent::unguard();
if( App::environment() === 'development' )
{
$this->call('UserTableSeeder');
}
}
Alternatively
Consider adding multiple database connections within your app/config/database.php file. That way, instead of seeding per environments, you can populate databases from multiple connections within the same environment (and the environment can still change but have 2 or more separate db connections).
If that fits your use case, see my answer on multiple database connections here.
My current system is using Zend Framework 1, and works very well with our local MySQL server. However, I now need to access another server for importing/exporting. I'm using a class extended from zend_db_table_abstract in order to query the necessary table.
class Model_Db_ExportData extends Zend_Db_Table_Abstract{
protected $_name;
protected $_schema;
}
I instantiate name and schema when I create the object
$export = new Model_Db_ExportData(array('name' => $this->exportTable, 'schema' => $this->db));
EDIT
From what I can gather, zend_db_table isn't the place to define the host, since it only affects tables. However, I'm still unable to figure out where I can define a host outside of configs.
EDIT
How do I specify a separate server from the one defined in my configs? Do I need to use custom configuration files for this code? The Zend_Db_Table_Abstract documentation wasn't very helpful, although it's quite large and I could have easily missed something. Any help is very much appreciated.
There are at least 2 possible ways to accomplish what you want:
Zend_Db_Adapter - check the examples there to see how to create an adapter with the remote server settings;
Zend_Config_Ini - create a file with the remote server settings and then call in your application.
I'm trying to write a webapp with CakePHP, and like most webapps I would like to create an installer that detects whether the database has been initialized and, if not, executes the installation process.
This process will be entirely automated (it assumes the database itself already exists, and that it is granted full administrative access through the anonymous account with no password...this is for a sandbox environment, so no worries about security), so it needs to be able to detect (regardless of the request!) if the database tables have been created and initialized, and if not, to perform that initialization transparently and then still serve up the user's original request.
I considered writing a sort of Bootstrap controller through which all requests are routed, and a single SQL query is run to determine if the database tables exist, but this seemed cumbersome (and the controller requires a corresponding model, which needn't be the case here). The other possibility is was to override AppModel and place within it the same test, but I was unsure how to do this, as there isn't any documentation along these lines.
Thanks in advance!
tl;dr version: What is the CakePHP equivalent (or how can the equivalent be written for CakePHP) of a J2EE servlet's "init()" method?
Check out the AppError class - may be there is a missing database table error that your can override and run your create database table SQL from there?
Something like this might do what you're looking for, but does require an extra query per model.
<?php
class AppModel extends Model {
var $create_query = false;
function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
if (!empty($this->create_query)) {
$this->query($this->create_query);
}
}
}
?>
Then you would just need to add var $create_query = 'CREATE TABLE IF NOT EXISTS ...;` in your models. The MySQL CREATE TABLE documentation has more information on IF NOT EXISTS.
However, I'm not certain that this isn't trying to call query() too early. Or before the check to see if the table already exists, which it would have to be. Otherwise, CakePHP would error out instead of creating your table. There isn't much documentation on the subject and your best bet for more information going to be to take a look at cake/libs/model/model.php directly.
Update: The code above would not work as written.
After looking into the Model class a little deeper, Model::__construct calls Model::setSource(). Model::setSource() checks to see if the table exists and throws an error if it doesn't. To use this method, that's where you'd have to override and insert the query. The code below may need to differ, depending on which version of CakePHP you're using.
<?php
function setSource($tableName) {
// From Model::setSource(). I believe this is needed to make query() work.
$this->setDataSource($this->useDbConfig);
// Create our table if we have a create query
if (!empty($this->create_query)) {
$this->query($this->create_query);
}
// Now call the parent
parent::setSource($tableName);
}
?>
Do you really want to make every request check that the database exists? This seems terribly wasteful.
The first time it checks it will set up the database, and then for every one of the next million requests it will check again even though the database has of course by this time been set up!
It's a better idea to require that whomever installs your application do some setup. You should provide a separate script that is not run during every request, but is run manually by the person during installation.
Re your comment about the best way to do this with CakePHP, have you looked at Cake's support for database schema migrations?
http://book.cakephp.org/view/734/Schema-management-and-migrations
I thought about doing this at one point in time, and came up with a good way to do it.
First off, a note: I believe your app needs write access to app/config/database.php, so you can write the correct information. I have a workaround, but let me explain the method by which the installer works.
PHP Scripts can rewrite themselves (or delete themselves) on the fly. Since the script is loaded into memory and THEN the bytecode is executed, it isn't dependent upon the file once it is done working. So you could theoretically have something that overrides the AppError class to run a specific controller (say your SetupWizardController) with all the regular, CakePHP stuff loaded. Once you go through the entire wizard, write the database.php file/setup anything else needed, overwrite the AppError and AppController files (I can see you needing the AppController to work differently if the app hasn't been installed in certain cases) with ones that are stored somewhere like in app/vendors/myapp. The script has finished executing and now your checks will not occur on subsequent runs.
This would get rid of the problem Bill Karwin brought up, utilize AppError, and make an installer.
The other way to do it is to include the idea of Environments in your application. Say you store your environments in app/config/environment.php. This file would be given write access to (and that access would be removed at the end of setup), or could be overwritten. Regardless, it would exist whenever someone attempts to deploy your application, and database.php automatically imports the databases from the environment.php file. The constructor of the database.php class would then overwrite it's $default database with the one specified in environment.php. The $default in database.php would reference a NoDB Datasource, which you can check in the AppController (I think you would be able to instantiate a dummy model and check it's datasource), and then push up the required Installer. Obviously you'd overwrite the AppController after this as well.