Tuesday, November 24, 2009

Cannot send session cache limiter

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent

If you encounter the above problem, try to set the encoding from UTF-8. UTF-8 encoidng add some characters before <?php

Tuesday, June 30, 2009

Access SimpleXMLElement Object Attributes

PHP simplexml_load_string is a simple way to extract xml data into an object. If you have the following result from calling

$obj = simplexml_load_string($xml);


SimpleXMLElement Object
(
[@attributes] => Array
(
[status] => success
)

[auth] => SimpleXMLElement Object
(
[token] => dxoYGmwncmntH07jJGro5h0rxNfE2Ni6
[seq] => 33
)

)


you can access status by

$obj->attributes()->status

Saturday, April 18, 2009

CakePHP 1.2 Versatile Model find('list')

Have you wanted to generate a list of options for your select but wanted the display field to be generated dynamically instead of using cakePHP find('list')?

This is the case.


MODEL
User hasOne Info

User
id
username
password
manager_id
Info
id
first_name
last_name
email
sex


I wanted to generate a list of all Users displaying the first_name, last_name and sex. And I wanted the indexes to be generated with User.id and the display field with this format "Info.last_name, Info.first_name (Info.sex)". I have developed a function to override cakePHP $model->find.

In your app_model.php, you include this function:

class AppModel extends Model {

function find($type, $options = array()) {
switch ($type) {
case 'superlist':
if(!isset($options['format'])) {
$options['format'] = '';
for ($i=0; $i $options['format'] .= "%$i ";
}
$options['format'] = trim($options['format']);
}

if (isset($options['index'])){
preg_match('/(.*?)\.(.*)/', $options['index'], $match);
$index_alias = $match[1];
$index_field = $match[2];
}else{
$index_alias = $this->alias;
$index_field = 'id';
}

$options['fields'] = array_merge(array("{$index_alias}.{$index_field}"), $options['fields']);
$list = $this->find('all', $options);

$result = array();
foreach ($list as $row){
$result[$row[$index_alias][$index_field]] = $options['format'];

foreach ($options['fields'] as $index=>$field){
preg_match('/(.*?)\.(.*)/', $field, $match);
$field_alias = $match[1];
$field_field = $match[2];

$result[$row[$index_alias][$index_field]] =
str_replace('%'.$index, $row[$field_alias][$field_field],
$result[$row[$index_alias][$index_field]]);
}
}

return $result;
break;

default:
return parent::find($type, $options);
break;
}
}

}


This is how you call the generate list function in your controller action.

// if you have not declared hasOne Info in User model, this is needed in order for User model generate Info model with it and you can pass condition on Info fields
$this->User->bindModel(
array(
'hasOne' => array('Info')
)
);

$users = $this->User->find('superlist',
array(
'format' => '%3, %2 (%1)',
'index' => 'User.id', // --> this is the default so you may not pass this option
'fields' =>
array(
'Info.sex', // --> %1
'Info.first_name', // --> %2
'Info.last_name', // --> %3
),
'order' => "Info.first_name, Info.last_name", // -- if you want to sort the option
'condition' => "User.manager_id=2 AND Info.lastname='Smith'", // --> if you need some filtering
)
);
$this->set(compact('users'));



$users array will contain the following structure:



array(
'User.id1' => 'Info.last_name1, Info.first_name1 (Info.sex1)',
'User.id2' => 'Info.last_name2, Info.first_name2 (Info.sex2)',
'User.id3' => 'Info.last_name3, Info.first_name3 (Info.sex3)',
.
.
.
'User.idN' => 'Info.last_nameN, Info.first_nameN (Info.sexN)',
)


Hope this post can help you in your future cakePHP 1.2 development.

Thanks to http://teknoid.wordpress.com/2008/09/04/findlist-with-three-or-combined-fields/ for giving me inspiration to develop this function.

Saturday, February 14, 2009

CakePHP Routing With Parameters

Anything you need to know with cakePHP routing can be found here.

Here is an example to illustrate routing with parameters.

/config/routes.php

Router::connect(
'/:controller/:year/:month/:day',
array('action' => 'index', 'day' => null),
array(
'year' => '[12][0-9]{3}',
'month' => '(0[1-9]|1[012])',
'day' => '(0[1-9]|[12][0-9]|3[01])'
)
);


Parameters can be access like this:

/controllers/controller.php

function index(){
// params is stored in $this->params
$year = $this->params['year'];
$month = $this->params['month'];
$day = $this->params['day'];

//
}

Friday, February 13, 2009

Increase Performance of Loop with Large Arrays

In PHP, this is how we usually loop through arrays:


<?php
for ($i=0; $i<count($big_array); $i++){
//
}
?>


Having this approach, program will try to count the $big_array every time it loops and it may cause some performance issues. To make it more efficient, we should code it this way:


<?php
for ($i=0, $n=count($big_array); $i<$n; $i++){
//
}
?>


It does the counting during initialization only.

How to Route Admin Actions in CakePHP 1.2

This is how to setup the routing:

Router::connect('/admin/:controller/:action/*', array('admin'=>'true','prefix'=>'admin', 'controller'=>'controller', 'action'=>'action'));

Thursday, February 12, 2009

Indenting Tree List in Form Input Select using '&nbsp;' as spacer

This is the scenario in cakePHP 1.2.

In your controller, you have an action:


function add() {
...
$categories = $this->Listing->Category->generatetreelist(null, null, null, '&nbsp;');
$this->set(compact('categories','keywords','metros','states'));
}


where '&nbsp;' is your spacer.

Your view will have something like this:


...
echo $form->input('Category');
...


The above combination will display a drop down menu with the '&nsbp;' printed as '&nbsp' and not as a space. So how would you do it in cakePHP 1.2?

The key here is in the view file.

instead of the above statement, you should have this:


...
echo $form->input('Category', array('escape' => false));
...


Hope this one helps.

Thursday, January 29, 2009

Merging Arrays Preserving the Numeric Keys

Merging arrays like this:

<?php
$array1 = array();
$array2 = array(1 => "data");
$result = array_merge($array1, $array2);
?>

will result to:

Array
(
[0] => data
)

Don't forget that numeric keys will be renumbered!

If you want to completely preserve the arrays and just want to append them to each other (not overwriting the previous keys), use the + operator:

<?php
$array1 = array();
$array2 = array(1 => "data");
$result = $array1 + $array2;
?>

The numeric key will be preserved and thus the association remains.

Array
(
[1] => data
)

Source: http://php.net/array_merge

Tuesday, January 27, 2009

Empty Options for cakePHP 1.2

$options['empty'], if set to true, forces the input to remain empty.

When passed to a select list, this creates a blank option with an empty value in your drop down list. If you want to have a empty value with text displayed instead of just a blank option, pass in a string to empty.

<?php echo $form->input('field', array('options' => array(1,2,3,4,5), 'empty' => '(choose one)')); ?>

Source: http://book.cakephp.org/view/201/options-empty

How to Include Javascript File in Cake PHP

If you want to use a Javascript file, you usually reference it in the head section of your layout:


<head>
<?php echo $javascript->link('script.js'); ?>
</head>


But sometimes you want to use a certain Javascript file only in one view. Then it doesn’t make sense to reference it in the layout. You could take the PHP statement from above and place it in your view, that will work. But it is not a clean solution as the Javascript reference is placed somewhere in the middle of the generated HTML code.

Fortunately, CakePHP 1.2 allows you to define a reference to a Javascript file which is then added to the head section of the generated HTML code. For this purpose the variable $scripts_for_layout has to be added to the layout:


<head>
<?php echo $scripts_for_layout; ?>
</head>



In the view you can now link to the Javascript file with:

$javascript->link('script.js', false);

Notice the second parameter. Set it to false to tell cake to put the reference in $scripts_for_layout variable in the layout file.

Source: http://cakebaker.42dh.com/2007/02/21/referencing-javascript-files/

PHP Ternary Operator

Consider the following snippet of code:


if (condition){
variable = value1;
}else{
variable = value2;
}


Instead of doing that way, we can just simply do it like this:

variable = condition ? value1 : value2;


Another variation of using the ternary operator would be from:


if (condition){
echo "something1";
}else{
echo "something2";
}


And it can be expressed like:

echo condition ? "something1": "something2";


You can also nest the condition:

variable = cond0 ? (cond1 ? value1.1 : value1.2) : (cond2 ? value2.1 : value2.2);


Just use your imagination on how to use this form.