Archive for the ‘model’ Category

How to extend a plugin indirectly

Wednesday, September 16th, 2009

I’m using CakePHP1.2.4
At times, I want to modify/extend a  plugin indirectly.

How do I do that?
It’s very simple, only import and inherit.

Here is the plugin(cakeplus) I made on the github.
http://github.com/ichikaway/cakeplus/tree

In this example ,   I use the behavior(add_validation_rule.php) of the cakeplus plugin and modify some method.

1. download the cakeplus plugin, and set in the “app/plugins” directory.
2. make new directory(cakeplusplus) in the “app/plugins”.

Now you can see directories as follow.


plugins/cakeplus/models/behaviors/add_validation_rule.php

plugins/cakeplusplus/models/behaviors/

3. create “ext_add_validation_rule.php”  file in “cakeplusplus/models/behaviors/” directory .


App::import('Model', 'cakeplus.AddValidationRule');
class ExtAddValidationRuleBehavior extends AddValidationRuleBehavior {

}

4. Now you can use the “ExtAddValidationRuleBehavior” class which has same functions as the “AddValidationRuleBehavior” class.

class Post extends AppModel {

var $name = 'Post';

//var $actsAs = array('Cakeplus.AddValidationRule');
var $actsAs = array('Cakeplusplus.ExtAddValidationRule');

}

5.If you want to modify or extend, you just override a method of the “AddValidationRuleBehavior” class in the “ExtAddValidationRuleBehavior” class as follow.
In this example, override the maxLengthJP method and change that function.

App::import('Model', 'cakeplus.AddValidationRule');
class ExtAddValidationRuleBehavior extends AddValidationRuleBehavior {

function maxLengthJP( &$model, $wordvalue, $length ) {
$word = array_shift($wordvalue);

//extend
$length = $length * 2;

return( mb_strlen( $word ) <= $length );
}
}

Use placeholder in Model::query() of CakePHP

Monday, August 10th, 2009

I’m using CakePHP1.2.3

Model::query() is very useful for writing SQL statements as follow.

<?php

$this->Model->query("SELECT `Post`.`id` FROM `posts` AS `Post` WHERE `Post`.`id` = 100", $cachequeries = false);

To avoid SQL Injection, we want to use placeholders instead of embedding user input value in the statement.
We use “?” character in the SQL statement, set array data in 2nd parameter of the query method.
If 2nd parameter is array data in query method, it executes DboMysql::value() for escape value, using the “mysql_real_escape_string” function.

<?php

$sql = "SELECT `Post`.`id` FROM `posts` AS `Post` WHERE `Post`.`id` = ? LIMIT ?";
$this->Model->query($sql, array(100,1), $cachequeries = false);

Cake constructs a SQL statement and executes as follow.

SELECT `Post`.`id` FROM `posts` AS `Post` WHERE `Post`.`id` = 100 LIMIT 1

References
http://book.cakephp.org/view/456/query
http://en.wikipedia.org/wiki/SQL_injection

Validation error message i18n

Thursday, July 23rd, 2009

In a Model, we can define validation error message as follow

<?php
class User extends AppModel {
	var $validate = array(
		'email' => array(
			"email_invalid" => array('rule' => VALID_EMAIL,
				'required' => true,
				'message'    =>    'Invalid Email address.',
	),

But, can not use i18n function __() for validation error messages .
This is a solution to do it.

<?php
class AppModel extends Model {

	//Validation message i18n
	function invalidate($field, $value = true){
		parent::invalidate($field, $value);
		$this->validationErrors[$field] = __($value, true);
	}
}

Model::invalidate method is called in validation processing(Model::validates , Model::invalidFields).
This solution override Model::invalidate and set __() in each error messsage.

Then, you write po file of each language, language of validation error messages change depending on browser language configuration.