cakePHP

Setting up multiple databases with cakePHP

Posted on: August 7th, 2009 by taff 1 Comment

 

Yet again I been pleasantly surprised at how easy cakePHP handles things. This time it's the use of multiple databases. The current setup of our system has data stored in 4 databases.

For our example we will presume our multiple databases are setup as such:

We have a users database (which contains everyone we have ever had contact with) and is used by our CRM software. We then have our database containing all the products that our application has stored.

Our first step would be to configure all our configurations in app/config/database.php. It could look something like this:

<?php
class DATABASE_CONFIG {
	var $default = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'hopefully_not_root',
		'password' => 'hardtoguess',
		'database' => 'products',
	);
	
	var $users = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'hopefully_not_root',
		'password' => 'hardtoguess',
		'database' => 'users',
	);
}
?>

I know it's hard to believe but cakePHP will use default if it's there. What an apt name! 😉

Our Products model will then look something like this:

class Product extends AppModel {

    var $name = 'Product';
    //The next line could be omitted...default is default 😉
    var $useDbConfig = 'default';
    
    //Validation etc.. could go here
    
} 

Our Users Model would look similar:

Our Products model will then look something like this:

class User extends AppModel {

    var $name = 'User';
    var $useDbConfig = 'users';
    
    //Validation etc.. could go here
    
} 

That's it.

$this->Product->find() will now query our products database, and $this->User->find() our users database.

Taff

Adding search engine friendly URL’s (Slugs)

Posted on: August 5th, 2009 by taff No Comments

 

I was looking for a quick way to add search engine optimised URL's to my cakePHP application and was amazed at how fast it was setup.

These are the (extremely simple) steps that I took.
Add a slug field to my database table

ALTER TABLE `the_table_name` ADD `slug` VARCHAR(255) NOT NULL;

Update our table to add slugs, related to the title

For the sake of ease I simply added an extra line to my edit method. This doesn't check anything and will resave the slug whenever the title is changed...but it worked for testing 😉

if (!empty($this->data)) {
$this->data['Controller']['slug'] = Inflector::slug($this->data['Controller']['title_we_want_adapted']);
if ($this->Controller->save($this->data)) { $this->Session->setFlash(__('Saved', true));
} else {
$this->Session->setFlash(__('Not saved. Please try again.', true));
}
}

Note our use of the built in Inflector::slug class method. We should probably have converted to lowercase too.

The next step was to change links that previously pointed to
/path/to/app/controller/method/id
to now point to
/path/to/app/controller/method/the_slug_we_generated

What's left to do? Well if we click on our newly generated link, it probably won't find the row it needs because it will be doing something like:

SELECT * FROM `the_table_name` WHERE `id` = the_slug_we_generated;

I personally already had a beforeFilter() in my controller to prevent users accessing Lists that didn't belong to them so I updated it in the following way to ensure that both slugs and id would work (May come in handy if people have links bookmarked with the old method).

function beforeFilter() {
parent::beforeFilter();
//Are there any parameters for this action, i.e. is it an edit or view
if(isset($this->params['pass'][0])){
$id=$this->params['pass'][0];
//Is it numeric, in which case its an id already (we hope at least)
if(!is_numeric($id)){
//If its a slug, we need the related item.
$new_id=$this->currList=$this->Dolist->find('first',array("conditions"=>array('Dolist.slug'=>$id)));
$id=$new_id['Dolist']['id'];
//So we know it's using a slug
$this->usesSlug=$id;
}
$this->currList=$this->Dolist->find('first', array("conditions"=>array('Dolist.id'=>$id)));
//Check User stuff
if($this->currList['Dolist']['user_id']!=$this->Session->Read('Auth.User.id')){
$this->Session->setFlash("You're not authorised to ".$act." ID:".$this->params['pass'][0]." or it no longer exists");
$this->redirect(array('action'=>'index'));

}

}
}

I then updated my view method

function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid Dolist.', true));
$this->redirect(array('action'=>'index'));
}
if($this->usesSlug!=0){
$id=$this->usesSlug;
}
//Carry on as normal....

For search engine optimisation we should probably set a redirect in the controller if it's an ID but thats up to you.

Don't you just love how easy things are to setup with cakePHP? 😉