Thursday, May 19, 2011

CodeIgniter - form_validation Errors with array Field Names

ok, another problem with Code Igniter. When the field name is an array, and there is validation performed on the  post values, if one of the fields has an array, this array will be applied to all the form_error().

e.g. You are building a list of questions as a survey and have this validation.
$this->form_validation->set_rules(‘questions[]’, ’Question Text', ‘trim|required|xss_clean’);

And in your view, you have
foreach ($questions as $qn)
{
  ...
  echo form_input(array('name'=>'question_text[]'));
  echo form_error(‘questions[]’);
  ...
}

In this case, if one of the questions text is empty, the "required" error will be triggered. And since the validation object only have 1 error param (print_r($this->_field_data) to know what I'm talking about), this same error will be applied to all the form_error();

So this is what I did (reference to Code Igniter 2.x)

1. In system/libraries/Form_validation.php (or you can subclass it, though this method is quite long and may not be so straight forward)
Look for :
function _execute($row, $rules, $postdata = NULL, $cycles = 0)
 {
  // If the $_POST data is an array we will run a recursive call
  if (is_array($postdata))
  {
   foreach ($postdata as $key => $val)
   {
    $this->_execute($row, $rules, $val, $cycles);
    $cycles++;
   }

   return;
  } 

Insert this after:
if ( $row['is_array'] )
  {
   $this->_field_data[$row['field']]['error'][$cycles] = '';
  }

Then look for this:
$this->_field_data[$row['field']]['error'] = $message;

We need to comment that out and new logic to handle the error array, so replace that line with this:
//$this->_field_data[$row['field']]['error'] = $message;
if ( $row['is_array'] )
    {
     $this->_field_data[$row['field']]['error'][$cycles] = $message;
    } else 
    {
     $this->_field_data[$row['field']]['error'] = $message;
    }

Step 2. create a file in /application/libraries/MY_Form_validation.php
class MY_Form_validation extends CI_Form_validation
{
 function __construct($config = array())
 {
  parent::__construct($config);
 }
 function error($field = '', $prefix = '', $suffix = '')
 {
  if ( ! empty($this->_field_data[$field]) 
   && $this->_field_data[$field]['is_array'])
  {
   return ($prefix?$prefix:$this->_error_prefix)
   .array_shift($this->_field_data[$field]['error'])
   .($suffix?$suffix:$this->_error_suffix);
  }
  
  return parent::error($field, $prefix, $suffix);
 }
}

Done!

I'll explain.

Step 1 turns the validation object error parameter into an array, and insert the error message only when there is a validation error. Else it creates an empty error array element.

Step 2 is to display the error message if it exists. Basically it uses the same logic of popping out the first error message (which may be a blank) like when we do a set_value('question[]);

So that's it.

May have bugs, use at your own risk.

Thursday, April 21, 2011

CodeIgniter - PATHS

CodeIgniter as a few reserved words that points to your application path, but it's not clear where they point to. The following is for windows on my dev machine, but applies to linux as well.

FCPATH=C:\xampplite\htdocs\appname\
BASEPATH=C:\xampplite\htdocs\
appname/system/
APPPATH=C:\xampplite\htdocs\appname/system/application/

So to point to some .dat files in your libraries dir (QR code), the string would be APPPATH.'libraries/qrcode/data'.

Friday, January 28, 2011

Ephemeralization

http://en.wikipedia.org/wiki/Ephemeralization

Check list

"There should be checklist for every station/position." - Apogee (ex RSAF Colonel)

Story of climbing a mountain

Got this from a senior management.

When we climb up a mountain, as the road is treacherous we have to move in a single file. In this way, the view of the leader will always be different from the others. When the group starts off on flat ground, everyone will think the going is easy. However, the leader will know that the climb is starting and the going will be difficult, so he has to plan for it. His view of the situation is different from the group.

As the group climbs and near the pinnacle, the leader will know this, and will brief a sigh of relieve. But the people following him cannot see th pinnacle yet, and will still think that there's more to go.

Similarly, when the group is walking down the hill, the leader will need to prepare for the next mountain to climb.

The morale of the story is that as a leader, you have to look at different things, plan ahead, and sometimes it may not be a popular decision, but it has to be made, as you should have the best view.

Friday, October 8, 2010

Codeigniter Loading Singleton

I tried many times to register at the codeigniter forum, but the captcha is not letting me through. So I'll do my update here.

From this: http://codeigniter.com/forums/viewthread/150117/
Ketama has an example to load a library that is a singleton. However, if you are on PHP 5.2 and lower, you will have a problem. You will get a "Paamayim Nekudotayim" error.


Basically, before PHP 5.3, you cannot call a static method where the class is a variable. So the line below will give you an error.
$CI->$classvar = $name::getInstance($config);

$name cannot be used to make a call to the static method of getInstance. There are two ways around this. First is to use the eval() command, but this is deemed to be up to 10 times slower (read this somewhere...no link), while the second solution of being 3 times slower seems to be the acceptable method. It is to do this:

$CI->$classvar = call_user_func_array(array($name,'getInstance'), $config);

By using the call_user_func_array() function, this will work with PHP versions older than PHP 5.3.

I've also made some minor changes to the code proposed to more suit my liking (in MY_Loader.php [CI version 1.72], subclass from CI_Loader and copy and paste the _ci_init_class() function and make the following change).
// Instantiate the class
$CI =& get_instance();
// modification start
if ($config !== NULL)
{
  if (isset($config['singleton']) ? 
    $config['singleton'] === TRUE : FALSE)
  {
    // for PHP 5.3 and above
    //$CI->$classvar = $name::getInstance($config); 
    $CI->$classvar = call_user_func_array(array($name,'getInstance'), $config);
  } else
  {
    $CI->$classvar = new $name($config);
  }//End If. Added support for singleton Libraries
} else
{
  $CI->$classvar = new $name;
}
// modification ends

To use, put the MY_Loader.php and your singletone file both into your system/applications/libraries/ directory. Then in your controller put in the following:

$this->load->library('MYLogger', array('singleton'=>TRUE));

That's all!

Thursday, February 11, 2010

Centralised Location-based Engine (CLBE)

With the new money being pumped into Wireless@SG, one of the new feature is providing LBS (Location Based Services).

The press release is here

From there you can goto the FAQ page.

So the question is that would you pay $200/mth for this?