ACL tables’ optimization for CakePHP 1.2.x.x
Are you concerned about how fast your queries are handled? Do you run a website with lots of AROs & ACOs? If you answered no to any of the previous questions, you can just skip reading because it’s not for you.
Ok - so let’s dive directly in, I am short on time but started liking this sharing knowledge stuff.
Right now, whenever DB_ACL::check() kicks in (whenever a user needs to get authorized for an action), there is 2 main SELECT queries and then, depending on the number of nodes in the path to get to that user’s group, there is another query for each (so a minimum of one). When I was running some tests (debug=2) today, I just couldn’t ignore the number of queries made on each page refresh, etc.
Continue reading…
I18n with dynamic content in CakePHP
Here’s a quick one I just happened to need. When you are a nitpick like me, you sure don’t like to see code like this:
__('Logged in with', true) . $username . __('on', true) . date('Y-m-d h:i:s');
For several reasons. First, it doesn’t look slick - and yes, for you that are reading and going to annoy me for the next week, when you read code all day for a living, it matters. But most importantly, how can you then change the place of words in your sentence?
Replace that with:
sprintf(__("Logged in with '%s on %s", true), $username, date('Y-m-d h:i:s');
Another gem found by reading the source code. Which reminds me that I should maybe make a post with all the little techniques I am learning from reading the code. I know not everyone enjoys reading the API, let alone the code itself. N’est-ce pas?
How to use AuthComponent in CakePHP
Wherever I went - irc, trac, google groups and certain blogs - I noticed people complaining about either not knowing how to use the AuthComponent or having problems with it.
After reading the only tutorials available across all usual blogs I rely on for all my CakePHP needs, I realized their was a gap I could fill. The reasons are:
- Lack of a CPC way for quick and easy implementation.
- No real explanation or solution for using in a real application environment (multiple controllers, beforeFiters, actions, etc.).
- Not covering the different authorization methods it’s capable of: default, controller, actions, crud, model and object
CakePHP URL validation bug fix and enhancement
Update: 25/10/2007 Bug appears to have been fixed in the latest pre-beta release. Looks like this was the correct regex.
When I started parsing the millions of Google pages scraped, I came across a bug with the URL validation. To fix that, I overwrote the url validation method in appmodel.php:
function url($check)
{
$validation =& new Validation;
$validation->check = $check;
$validation->regex = '/^((https?|ftps?|file|news|gopher)://)?' //protocol
. '('
. '(?:(?:25[0-5]|2[0-4]d|(?:(?:1d)?|[1-9]?)d).){3}(?:25[0-5]|2[0-4]d|(?:(?:1d)?|[1-9]?)d)' //ip 199.194.52.184
. '|' //ip or domain
. '([0-9a-z]{1}[0-9a-z-].)‘ //subdomain(s) www.
. ‘([0-9a-z]{1}[0-9a-z-]{0,56}).’ //domain
. ‘([a-z]{2,6}|[a-z]{2}.[a-z]{2,6})’ //tld
. ‘(:[0-9]{1,4})?’ //port
. ‘)’
. ‘(’
. ‘/?|’ //ending-slash
. ‘/[w-.,’@?^=%&:;/~+#]*[w-@?^=%&/~+#]’ //path
. ‘)$/i’;
return $validation->check();
}
Continue reading…
CakePHP’s advanced model fields validation
After checking different blogs and tutorials, the bakery, API and IRC channel, it was obvious that some kind of documentation for the validation methods available in the Model was necessary. I can’t say that I will fulfill this mission but I’ll at least share what I came up with for future reference.
Here is the ‘User’ model I will be using in my example:
class User extends AppModel
{
var $name = 'User'; //optional
var $validate = array(
‘username’ => array(
array(
‘allowEmpty’ => false,
‘required’ => true,
‘rule’ => ‘alphaNumeric’,
‘message’ => ‘Username should only contain alpha-numeric characters.’,
),
array(
‘rule’ => array(’between’, 3, 10),
‘message’ => ‘User should be between 3 and 10 characters long.’,
),
array(
‘rule’ => ‘isUnique’,
‘message’ => ‘Username is already in use.’,
),
),
‘passwd’ => array(
‘alphaNumeric’ => array(
‘allowEmpty’ => false,
‘required’ => true,
‘rule’ => ‘alphaNumeric’,
‘message’ => ‘Username should only contain alpha-numeric characters.’,
),
‘validLength’ => array(
‘rule’ => array(’between’, 3, 10),
‘message’ => ‘User should be between 3 and 10 characters long.’,
),
),
‘website’ => array(
array(
‘rule’ => ‘url’,
‘on’ => ‘update’,
‘message’ => ‘Invalid URL.’,
),
),
‘agree_tos’ => array(
array(
‘allowEmpty’ => false,
‘required’ => true,
‘on’ => ‘create’,
),
),
);
);
}
That’s a lot of validation rules, I know - I just wanted to try covering the multiple ways of using the Model->validates() method.
Continue reading…
SELECT DISTINCT in CakePHP
Even though CakePHP’s model already includes many of the database query functions, I found that the SELECT DISTINCT was missing. Ok, I know that you can always do it using either Model->query('SELECT DISTINCT or c1, c2)Model->findAll(null, 'DISTINCT but that would be like saying use c1, c2‘)Model->query() instead of Model->findAll().
The cool thing in CakePHP is that you can add your own functions to use in your app on top of the ones that come bundled in the core. For the Model, you just create an ‘app_model.php’ file that you place in our app’s main folder. The empty file should look like this:
/**
* Custom AppModel that adds functionality to the core Model
*/
class AppModel extends Model
{
//empty
}
Now inside your new AppModel class, add the following function:
/**
* Returns a resultset array with DISTINCT fields from database matching given conditions.
*
* @param mixed $conditions SQL conditions as a string or as an array('field' =>'value',...)
* @param mixed $fields Either a single string of a field name, or an array of field names
* @return array Array of records
*/
function findDistinct($conditions = null, $fields = null)
{
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$str = 'DISTINCT ';
if (!is_array($fields))
{
$str .= '`' . $fields . '`';
}
else
{
foreach ($fields as $field)
{
$str .= '`' . $field . '`, ';
}
$str = substr($str, 0, -2);
}
$queryData = array(
'conditions' => $conditions,
'fields' => $str,
);
$data = $db->read($this, $queryData, false);
return $data;
}
You can now use Model->findDistinct('c1') or Model->findDistinct(array('c1', 'c2', 'c3')) to retrieve DISTINCT columns values.
Hoping you find it useful.
Configuring CakePHP for easy deployment
Whenever you are developing an application, you are normally using at least 2 environments: development and production. Depending on how big your app and database are, deployment may become a long list of to-dos in order to have everything setup correctly (database changes, code merges, apache configuration, etc.). When you want to do things the right way, you usually have a 3rd environment, staging. Yes, another almost identical to-do list.
Now imagine you are developing in a team with each member working on a different part of the application in individual branches on the repository. New features are only merged with the team’s branch (development) after they are tested individually. So now, you have to deploy from individual to development, then to staging before finally pushing updates to production.
This time-consuming process is definitely not the best solution, put aside the fact that it is bound to break with any mistake while reconfiguring everything. Today, we will automate CakePHP’s configuration for easy deployment. Continue reading…

