I am using CakePHP v2.x. My current Database is MySQL. My need is to connect to other Database within a method/function written under controller. So what I did so far is add another DB connection array $test in Config/database.php.
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'test',
'password' => 'test1',
'database' => 'test_portal',
'prefix' => ''
//'encoding' => 'utf8',
);
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'dfffd_23',
'password' => 'dsfsd324',
'database' => 'testdbuser',
'prefix' => ''
//'encoding' => 'utf8',
);
}
I need to connect a table named 'aezips'.So I created a new Model;
class Aezips extends AppModel {
public $name = 'Aezip';
public $useDbConfig = 'test';
//public $useTable = 'aezips';
}
In my controller added ;
public $uses = array('Aezip');
Controller having a function/method named add,
public function add() {
$this->layout = NULL;
$this->autoRender = false; //will prevent render of view
if($this->RequestHandler->isAjax()){
Configure::write('debug', 0); //it will avoid any extra output
}
//$this->Aezip->useDbConfig('test');
$t = $this->Aezip->find('all'); //To fetch data from aezips table
print_r($t);
print_r($this->data);
}
But I can't connect to Aezip table and it doesn't shows any error. Both Database residing from same server but different cpanel account.
You seem to have used the wrong name for your Model (plural instead of singular);
class Aezips extends AppModel {}
Should be:
class Aezip extends AppModel {}
And the right filename should be app/Model/Aezip.php
Also, be sure to enable 'debug' inside app/Config/core.php so that you can see the queries that are performed. Also, this will refresh the CakePHP caches more often, which will reduce the risk of using 'cached' Model definitions.
You can debug your variables using debug($variable); in stead of print_r($variable);
Related
Using CakePHP 2.2.3
I'm nearly finished with my project and now going back through to setup authorization.
I'm implementing ACL, truncated both the users and groups tables for a fresh start, ran the command to recreate the aco/aro/aros_acos tables and have followed the tutorial.
When I create a group, it creates a corresponding ARO entry but the lft, and rght fields are NULL. I commented out all of my other code in the users/groups models and controllers to try to narrow it down, but it doesn't seem to help.
I will post my code below, with comments and validations removed for the sake of space.
group model:
App::uses('AppModel', 'Model');
class Group extends AppModel {
public $actsAs = array('Acl' => array('type' => 'requester'));
public function parentNode() {
return null;
}
public $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
User model:
App::uses('AppModel', 'Model');
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
//setup ACL settings and function
public $actsAs = array('Acl' => array('type' => 'requester'));
public function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
if (isset($this->data['User']['group_id'])) {
$groupId = $this->data['User']['group_id'];
} else {
$groupId = $this->field('group_id');
}
if (!$groupId) {
return null;
} else {
return array('Group' => array('id' => $groupId));
}
} // end parentNode()
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
AppController:
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
//'Security',
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)/*,
'authenticate' => array(
'Form' => array(
'scope' => array('User.activated' => 1 )
)
) */
),
'Session'
);
public $helpers = array(
'Html',
'Text',
'Session',
'Form'
);
/* public function isAuthorized($user = null) {
return true;
} */
public function beforeFilter(){
$this->Auth->loginRedirect = array('controller' => 'products', 'action' => 'index' );
$this->Auth->logoutRedirect = array('controller' => 'products', 'action' => 'index');
$this->Auth->authError = 'You are not allowed to see that.';
}
I even did an ACL implementation on a fresh install of cakephp 2.4.6, and everything works great. I have the projects side by side for comparison but can't find a difference in my ACL setup
Why aren't my lft and rght fields being set in my ARO table?
Short Answer: Remove MVC files associated with ACL tables.
Less Short Answer:
I setup ACL on a fresh install of cake 2.2.3, and everything worked great. Overwrote my code from my user and group models and controllers as well as AppController, and still no go.
I've seen a similar situation when I forget to add $actsAs = array('Tree'); to a model.
I realized I baked controllers/models/views for all ACL tables. DOH! (look for aroscontroller, acoscontroller, etc.)
I removed all the MVC files for these tables and it works great now.
This isn't a typical issue since normally one would add ACL schema after baking, but I started with a database I used on another project and forgot to remove the tables.
I really hope my stupidity helps someone else in this situation.
I'm building a Website in Cakephp with variable databases.
I did this with the following code:
CONTROLLER:
$db_host = $DB_SET['Project']['db_host']; //From other database
$db_user = $DB_SET['Project']['db_user'];
$db_pass = $DB_SET['Project']['db_pass'];
$db_database = $DB_SET['Project']['db_database'];
ConnectionManager::create("client_db", array(
'datasource' => 'Database/Mysql',
'driver' => 'mysql',
'persistent' => false,
'host' => $db_host,
'login' => $db_user,
'password' => $db_pass,
'database' => $db_database,
'prefix' => '',
'encoding' => 'UTF8',
'port' => '',
));
$DB_LINE = $this->Page->findPage('3');
MODEL:
class Page extends Model {
public $useDbConfig = 'client_db';
function findPage($pagenr) {
$page = $this->find('first', array(
'conditions' => array (
'Page.id' => $pagenr)
));
return $page;
}
}
Now I also need to change of tables in the database on the Fly.
I do this using(Controller):
$tbl_current = array('tbl_cheques', 'tbl_wishes');
$this->Modelname->useTable = $tbl_current[$pageid]; //Getting the pageID from an url parameter.
Everything works fine, only if I don't wait a while before clicking another page I get this error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Page.fqlkdf' in 'field list'
This because Cake still have the previous table in his Cache.
If I wait a minute and then I change the page it works fine.
Any suggestions for this problem?
Thanks in advance,
AƤron
Like you said, the table info is cached. So you just need to remove that cache:
Cache::clear(false, '_cake_model_');
Or, you can just temporarily disable cache
Configure::write('Cache.disable', false);
I was wondering is there a way i can set up the config where i can have two database entries that work when the environment is Local and when on Server.
I had come across a solution long time back on doing the switch through the code. Not able to find it now. How do you guys do it ?
I have a setup with local config files. I add the following lines at the bottom of app/config/core.php:
if(file_exists(ROOT.'/app/config/core.local.php')) {
include_once(ROOT.'/app/config/core.local.php');
}
In core.local.php I can override all the settings that differ on the local machine. The same goes for database.php.
I use a config class which does exactly that:
http://www.dereuromark.de/2010/08/17/development-vs-productive-setup
Recently I rewrote it for 2.0 as a plugin version.
It now takes care of test environments and cuts down the number of lines of configuration you will have to write:
http://www.dereuromark.de/2012/02/25/dynamic-database-switching/
I think it based on IP
at local environment IP is 127.0.0.1
and at live environment IP is never 127.0.0.1
My view
Thanks
check with the lib/Cake/Utility/String.php see the function named
public static function uuid()
cheers
Thanks again
This worked
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'username',
'password' => 'password',
'database' => 'database_name',
'prefix' => '',
//'encoding' => 'utf8',
);
public $live = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'db.HOST.net',
'login' => 'username',
'password' => 'password',
'database' => 'database_name',
'prefix' => '',
//'encoding' => 'utf8',
);
public function __construct(){
if (isset($_SERVER) && isset($_SERVER['SERVER_NAME'])) {
if (strpos($_SERVER['SERVER_NAME'], 'localhost') === false) {
$this->default = $this->live;
}
}
}
}
I have an application where each subscriber gets their own 'app' folder within their own url eg.
www.domain.com/1234 subscriber1
www.domain.com/2345 subscriber2
now the db connection is configured in a class in config/database.php. I want to be able to change the database used based on the url (eg. /1234 = db_1234).
How would I achieve this?
Thanks
BTW I am using CakePHP 2.0
My previous solution was a load of rubbish. So I thought about attacking the problem from a different angle. My DATABASE_CONFIG class (/app/Config/database.php) now looks like this:
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => '127.0.0.1',
'login' => 'xxxx',
'password' => 'xxxx',
'database' => 'xxxx',
'prefix' => '',
'encoding' => 'utf8',
);
public $site_one = array(
'datasource' => 'Database/Mysql',
'host' => '127.0.0.1',
// ...
);
public $site_two = array(
'datasource' => 'Database/Mysql',
'host' => '127.0.0.1',
// ...
);
public function __construct()
{
if (strpos(env('HTTP_HOST'), 'site_one') !== false) {
// use site_one database config
$this->default = $this->site_one;
// elseif site_two
} elseif (strpos(env('HTTP_HOST'), 'site_two') !== false) {
// use site_two database config
$this->default = $this->site_two;
}
}
}
When Cake loads, the construct is now called automatically, and this sets the 'default' database connection dependent on the host.
Ah I got it now,
I thought DATABASE_CONFIG was called statically so didn't think to use the construct.
www.domain.com/12345678
function __construct() {
// get folder
if(substr(php_sapi_name(), 0, 3) == "cli") {
$j = explode("/", $_SERVER['PWD']);
$this->default['database'] = "sa_".$j[count($j)-1];
} else {
$j = explode("/", $_SERVER['REQUEST_URI']);
$this->default['database'] = "sa_".$j[1];
}
}
but commandline bake must be done in folder eg. 12345678/
I would like to write a cake shell to do a nightly backup of my database using mysqldump. I could do this as a shell script, but if I can cram it into a CakePHP shell, then I will get the added benefit of it working across both the development and live server, if I can get it to automagically read my database config settings. I will cron the cake shell and have some peace-of-mind knowing that I have frequent backups of my DB.
In my shell I'm trying to build up a string which starts with "mysqldump --user=" and I'd like to get the username from app/config/database.php. How can I get at the data in database.php?
In cake 2.1 the format has changed to:
App::uses('ConnectionManager', 'Model');
$dataSource = ConnectionManager::getDataSource('default');
$username = $dataSource->config['login'];
The following snippet should do the trick:
App::import('Core', 'ConnectionManager');
$dataSource = ConnectionManager::getDataSource('default');
$username = $dataSource->config['login'];
In CakePHP 3.x the format has changed to -
use Cake\Datasource\ConnectionManager;
$source = ConnectionManager::get('default');
debug($source); #Debugging the result
Result :
object(Cake\Database\Connection) {
'config' => [
'password' => '*****',
'username' => '*****',
'host' => '*****',
'database' => '*****',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
'url' => null,
'name' => 'remote'
],
'driver' => object(Cake\Database\Driver\Mysql) {
'connected' => false
},
'transactionLevel' => (int) 0,
'transactionStarted' => false,
'useSavePoints' => false,
'logQueries' => false,
'logger' => null
}
Get the Result :
debug($source->config()); #Accessing the result
Result :
[
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'username',
'password' => 'password',
'database' => 'database',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
'url' => null,
'name' => 'remote'
]
Just for sharing.
For any cakephp project, if using php as cronjob or command line to do large data processing I would build a standalone php script without cakephp, the reason for doing this because cakephp is slow (e.g. read & process 100K records).
To make my life simple I put all my standalone scripts under app/Vendor/myscripts/ (e.g: app/Vendor/myscripts/process.php)
below also the basic code to make sure you use the same database settings in standalone script with cakephp (tested with MySQL)
require_once '/XYZ/app/Config/database.php';
$database = new DATABASE_CONFIG;
try{
$dblink = new PDO('mysql:host='.$database->default['host'].';dbname='.$database->default['database'], $database->default['login'], $database->default['password'], array(PDO::ATTR_PERSISTENT => false));
$dblink->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dblink->exec('SET CHARACTER SET '.$database->default['encoding']);
} catch (Exception $e) {
die('DB Error'. $e->getMessage());
}
Example in controller, Change multi DB for DataSources in CakePHP 2.5.x
App::uses('AppController', 'Controller');
class DemoController extends AppController {
public $uses = array('AppModel', 'GVA21', 'GVA01', 'GVA14', 'GVA24' );
public function test_dbs(){
$this->autoRender=false;
// Load ConnectManager
App::uses('ConnectionManager', 'Model');
// DataSource ['default']
$MDM = $this->GVA14->find('count');
echo "MDM.GVA14\n<br>";
debug($MDM);
// Get DataSource Config DB ['default'] and ['SRL']
$confDeafult = ConnectionManager::$config->default;
$confSrl = ConnectionManager::$config->SRL;
// Change DataSource ['SRL']
ConnectionManager::drop('default');
ConnectionManager::create('default',$confSrl); //<== Is permanet change Find All models Down
// $this->GVA01->setDataSource('SRL'); //<== Is temp change Find model
echo "SRL.GVA14\n<br>";
$SRL = $this->GVA14->find('count');
debug($SRL);
$SRL = $this->GVA01->find('count');
echo "SRL.GVA01\n<br>";
debug($SRL);
$SRL = $this->GVA21->find('count');
echo "SRL.GVA21\n<br>";
debug($SRL);
// Change to DataSource ['default']
debug(ConnectionManager::drop('default'));
ConnectionManager::create('default',$confDeafult); //<== Is permanet change Find All models Down
//$this->GVA01->setDataSource('default'); //<== Is temp change Find model
$MDM = $this->GVA01->find('count');
echo "MDM.GVA01\n<br>";
debug($MDM);
$MDM = $this->GVA21->find('count');
echo "MDM.GVA21\n<br>";
debug($MDM);
////FIN
exit('FIN');
}