Planet CakePHP With Multiple Feeds

Short of having an actual announcement feed for Planet CakePHP, this seems like the fastest way to get information to all you subscribers. ;)

If you were wondering about the few non-English items showing up in the feed, you actually have a choice to subscribe to a separate feed which aggregates websites written in English/Portuguese/Spanish. Of course, it ain’t gonna stop there. The plan is to have all CakePHP-related websites aggregated regardless of language. That’s why it is called the Planet right?

Thanks/Obrigado/Gracias to everyone for submitting websites to be added. Keep them coming!

Bookmark and Share
Posted in Uncategorized | Tagged , | Leave a comment

CakePHP Losing or Missing Session?

I have my fair share of problems with session in Cake so I thought I can share the two important configurations in app/config/core.php which affects how Cake handles the session.

Session.checkAgent
Setting this to TRUE means Cake will store the user agent header of a request when a new session is created. On subsequent request, the user agent header sent is compared with the value stored in the session. If it does not match, the current session will be destroyed and a new session gets created.

This rarely causes problem unless you have embedded Flash or Java objects making separate requests to the application. You must take note to send the user agent string of the browser in that case. If you are using something like Aurigma’s Image Uploader where the user agent is not configurable, you have to set this to FALSE instead.

Security.level
Besides the session timeout, this will affect whether the session ID gets regenerated between requests and whether session.referer_check is set.

With session ID regenerated, there will be problems when your application does any Ajax calls. An Ajax request does not set the cookie as requested by the server which causes the browser to send the session ID of a previous request which will have already been destroyed.

Referrer check is done on the hostname level in Cake and in theory it should not cause any problems. Weirdly, I have a one time login link which redirects user to another location and it works in Firefox but not Internet Explorer. My guess is that Internet Explorer does not set the referrer header properly if it gets redirected. You can log the HTTP_REFERER headers to verify that though.

Anyways, the valid values:

  • high” – session ID regenerated and referrer check set
  • medium” – referrer check set
  • low” – none
Bookmark and Share
Posted in Uncategorized | Tagged , , | 14 Comments

Soft Deletable Behavior and the Model::exists() gotcha

If you ever used the Soft Deletable Behavior, you will realise that Model::del() always returns a FALSE. This is expected after knowing that the behavior intercepts the delete request by saving the deleted flag and date then returning FALSE so the actual delete don’t happen.

So since I can’t rely on the returned value of Model::del(), this is what I thought will work until one fine day the application returns a failure when the record seems to be soft deleted correctly.


// some action of a controller
$this->Model->id = (int) $idPassed;
$this->Model->del();

if ($this->Model->exists()) {
    // say success!
} else {
    // say failure!
}

Alas, Model::exists() sets callbacks to FALSE in its find('count') call. So this means no beforeFind nor afterFind callbacks gets executed. This is understandable since Model uses exists() in many places where it needs to reflect true existence. So to get the expected results, we have to set callbacks to TRUE instead.


$this->exists(array('callbacks' => true));
Bookmark and Share
Posted in Uncategorized | Tagged , , | Leave a comment

SingNet External Proxy IP Woes

Always get kicked out of your phpBB administration panel? Or the Apple Developer Connection? Assumed that SingNet can’t care less bout that 1/10000 website that don’t work for you and thus thought there was nothing you can do? OK, that was me until I asked with just 1% hope that there actually is a solution. I may be lucky since this is the first time I spoke to a technical support person that actually understand my problem without giving me a list of canned replies.

Check if your external IP keeps changing by refreshing the page over at WhatIsMyProxy.com. Try using proxy.singnet.com.sg:8080 as your browser proxy and problem solved.

Bookmark and Share
Posted in Uncategorized | Tagged | 4 Comments

From wordpress on iphone

I am happy with my iPhone purchase! Woot!

Bookmark and Share
Posted in Uncategorized | Tagged | Leave a comment

Multiple Validation Sets in CakePHP

Jonathon Snook wrote about multiple validation sets in CakePHP and it reminded me how often we require rather different sets of validation rules for a single model. I have always enjoyed learning how others approached similar problems so I think I shall share mine too.

A very relevant example is the User model where we usually have multiple forms associated. E.g. sign up, profile updates, password reset, etc. Each form have a different set of fields while some share the same fields. My approach is to select a different set of fields for each “action” and modify the rules if required. This means I’ll keep a master set of rules for all the User model fields and call setValidate() for each “action”.

/**
 * Set the default validation rules here.
 *
 * @var array
 */
	protected $_validate = array(
		'username' => array(
			'empty' => array(
				'required' => true,
				'rule' => VALID_NOT_EMPTY,
				'last' => true
			),
			'invalid' => array(
				'rule' => '/^[\w]{3,30}$/',
				'last' => true,
				'on' => 'create'
			),
			'exists' => array(
				'rule' => 'validateUniqueUsername',
				'last' => true,
				'on' => 'create'
			)
		),
		'password' => array(
			'empty' => array(
				'required' => true,
				'rule' => VALID_NOT_EMPTY,
				'last' => true
			),
			'invalid' => array(
				'required' => true,
				'rule' => '/^.{6,30}$/',
				'last' => true
			)
		),
		...
	);
/**
 * Sets just enough fields for validation.
 *
 * @param array $fields List of field names to validate against. If no param
 *                      passed, all fields will be included.
 * @author Derick
 */
	function setValidate($fields = null) {
		if ($fields === null) {
			$this->validate = $this->_validate;
		} else {
			$this->validate = array();
			foreach ($fields as $f) {
				if (isset($this->_validate[$f])) {
					$this->validate[$f] = $this->_validate[$f];
				}
			}
		}
	}

This is a simplified example in my User model where I have the register() function to validate only the fields required for sign up and the updateProfile() function which uses another set of fields with slight different requirement.

function register($data) {
	$fields = array('username', 'password', ...);
	$this->setValidate($fields);
	$this->save($data, true, $fields);
}

function updateProfile($data) {
	$fields = array('password', ...);
	$this->setValidate($fields);

	// derick: allow user to left password field empty
	unset($this->validate['password']['empty']);
	$this->validate['password']['invalid']['allowEmpty'] = true;
	$this->save($data, true, $fields);

	// derick: you can also call this again to "reset" to the default set of
	// rules but usually we don't need this
	$this->setValidate();
}

In other words, I only update the $validate array in the model when required. Some might think it is dangerous since there is a chance of saving data without validation but this works for me. What do the rest of you do?

Bookmark and Share
Posted in Uncategorized | Tagged , | 1 Comment

Extracting PO file with CakePHP I18n Shell

I have always been religiously wrapping __() and __n() around my texts knowing that it needs to be localized some day. Then it got to me that I never knew how to actually localize it! Out of curiosity, I went ahead to extract the PO file using the I18n shell.

What it does is basically look through your entire app folder for files and within each file extract all instances of __() and gang, then grab the tokens necessarily for building the PO file. Now, this is where it gets picky.

// error! invalid marker content!
__('Delete post #' . $id);
__n('comment', 'comments', $array[0]);
__n('comment', 'comments', $object->noOfComments());
__n('comment', 'comments', (int) $noOfComments);

// valid! it makes it easier to translate anyways
sprintf(__('Delete post #%d', true), $id);
// just $var will work, nothing funky
sprintf(__n('%d comment', '%d comments', $noOfComments, true), $noOfComments);

So if you are thinking of using the I18n shell, you should take note that the text to be translated should really be one single token. Also, the generated file has an extension of .pot but it should really be renamed to .po instead since Cake expects .po files in the locale folder.

Bookmark and Share
Posted in Uncategorized | Tagged , | 1 Comment

Welcome to Derilicious

I have always wanted a blog to note down things I have learn along the way and hope that in the process, it will help someone else too. So after several failed attempts to start blogging, I am happy that I have finally broken out of procrastination.

Why Derilicious? I can’t think of anything better and besides, I guess it is the content that matters. Hope you will find this blog as useful as I think it will be. Cheers.

Bookmark and Share
Posted in Uncategorized | Tagged | Leave a comment