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
I know I can’t cover everything at once, I just don’t have the time for it, but I will start with the first two and probably cover the third part in a serie of posts.
Continue reading…
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 app_model.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();
}
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…
Domain TLD Parser
Parsing URLs in PHP isn’t perfect. Don’t get me wrong here, it does the job when it comes to breaking the URL in logical parts, but, it doesn’t have any options to parse the host into domain name, TLD and sub-domain(s). Most probably because new TLDs are coming out from time to time and they want to avoid having to update that same function with every new TLD release.
To over-come this limitation and because I needed some way of extracting the domain, sub-domain and TLD out of each given URL, I came up with the following class: Domain TLD Parser
It parses hosts with all kinds of different TLDs, even the country-specific ones like ‘.co.za’, ‘.ne.jp’ or ‘.ltd.uk’. Here is an example:
<?php
$url = $_SERVER['HTTP_REFERER'];
include('/path/to/domain_tld_parser.class.php');
$domain = new DomainTldParser;
echo '<pre>';
print_r($domain->parse($url));
echo '</pre>';
?>
DocBlock and svn:keywords
In the application’s coding conventions (which I am almost done writing), I took the time to elaborate about code documentation and the use of phpDocumentor. Among the things discussed, there is the DocBlock, the header template of each PHP file and which looks something like that:
/** * Short description for file. * * Long description for file * * PHP 5 * * Copyright (c) 2007, Company Name * Street address * City, State, Zip * * * @filesource $HeadURL$ * @copyright Copyright (c) 2007, Company Name * @link http://www.companywebsite.com CompanyName * @package #### PACKAGE NAME #### * @sub-package #### SUBPACKAGE NAME #### * @since #.#.# //Correct version number as needed * @version $Revision$ * @author Your Name * @modifiedby $LastChangedBy$ * @lastmodified $Date$ */
Now you might be asking yourself what are all those $HeadURL$, $Revision$, etc. Those are ‘keywords’ for Subversion which can be dynamically updated on every commit. By default, Subversion doesn’t substitute those keywords but you can easily set that directly from the shell using:
$ svn propset --recursive svn:keywords 'HeadURL Revision LastChangedBy Date' /path/to/repo
Or, in case you are using TortoiseSVN, from the right-click menu of your repository’s folder - TortoiseSVN > Properties > Add. You can then enter ’svn:keywords’ in the ‘property name’ field and ‘HeadURL Revision LastChangedBy Date’ in the ‘property value’ field. Don’t forget to check the ‘apply property recursively’, otherwise, make sure you are only setting it on a file not a directory.
From the svn propset help shell command:
The svn:keywords, svn:executable, svn:eol-style, svn:mime-type and svn:needs-lock properties cannot be set on a directory. A on-recursive attempt will fail, and a recursive attempt will set the property only on the file children of the directory.

