Codeigniter 2 - Callback function in My_Controller

2019-01-29 03:38发布

问题:

I have all my callback functions in My_Controller so that they are not repeated throughout the website. This works fine but for some reason one of my functions is not working when I am posting information using AJAX but is working on other pages. The message I get back when I use the callback is:

Unable to access an error message corresponding to your field name.

But then I've created a message for it using set_message() and it works fine on the other page without AJAX.

If you were interested in the log, here is the relevant output when entering an invalid date:

ERROR - 2013-05-24 16:03:08 --> -----Valid date format called, 223013-05-15
ERROR - 2013-05-24 16:03:08 --> -----Should be okay = , 223013-05-15
ERROR - 2013-05-24 16:03:08 --> -----Valid date format = false, 223013-05-15

And with a valid date:

ERROR - 2013-05-24 16:06:00 --> -----Valid date format called, 2013-05-24
ERROR - 2013-05-24 16:06:00 --> -----Should be okay = , 2013-05-24
ERROR - 2013-05-24 16:06:00 --> -----Valid date format = true, 05,24,2013

Here is the callback:

class MY_Controller extends CI_Controller
{
    var $options;
    public function __construct()
    {
        parent::__construct();
        date_default_timezone_set('Europe/London');

        $this->options->calendar = FALSE;
    }

  //Check date format aggainst mysql format, valid dates only, no 30-2-2010.
  function _Valid_Date_Format($date)
  {
    log_message('error', '-----Valid date format called, '.$date);

    if( empty($date) )
    {
        $this->form_validation->set_message('_Valid_Date_Format', 'This date is required.');
        return FALSE;  
    }
    else
    {
        log_message('error', '-----Should be okay = , '.$date);
    }

    $parsed = explode('-',$date);

    if( checkdate($parsed[1],$parsed[2],$parsed[0]) )
    {
      log_message('error', '-----Valid date format = true, '.$parsed[1].','.$parsed[2].','.$parsed[0]);
      return TRUE;
    }

    log_message('error', '-----Valid date format = false, '.$date );

    $this->form_validation->set_message('_Valid_Date_Format', 'The Date entered is invalid.');
    return FALSE;
  }
}

Here is the AJAX Code:

//Submit time feature $("#submit_time").click(function() { var cct = $.cookie('csrf_simple_cookie');//Overcome ajax limitation with csrf function, see below:

        $.ajax({
        url: folder,
        type:"POST",
        context: document.body,
        data: {t_id:$('#t_id').val(),
        time_for:$('#time_for').val(),
        hrs_spent:$('#hrs_spent').val(),
        mins_spent:$('#mins_spent').val(),
        timer_description:$('#timer_description').val(),
        date_worked:$('#date_worked').val(),
        csrf_simple_collab:cct},
        dataType: "json",
        error: function(XMLHttpRequest,error)
        {
            if(error=='parsererror')//Not logged in.
            {
                window.location.replace(loginFolder)//redirect to login page
            }
        },
        success: function(data)
        {                   
              if(data.success)
              {
                    var message=$('#message-box').html('<span>Time data added successfully.</span>').hide();
                    message.fadeIn("slow"); 
                    javascript:location.reload(true);
              }
              else
              {
                    if(data.validation)
                    {
                        //var message=$('#message-box').html("<span>Database error</span>");
                        var message=$('#message-box').html(data.error);
                    }
                    else
                    {
                        var message=$('#message-box').html(data.error);
                        $('#time-for-error').html(data.time_for);
                        $('#date-worked-error').html(data.date_worked);
                        $('#mins-spent-error').html(data.mins_spent);
                        $('#hrs-spent-error').html(data.hrs_spent);
                        $('#timer-description-error').html(data.timer_description);
                    }
              }          
        }
        });

return false;

});

Here is the view:

    <?
        //If we are an admin we can alter the user the information is added for.            
        if($this->session->userdata('userType')=='admin'): ?>
        <div class="form_row">
            <div class="form_field">
                <label for="time_for">User:</label> 
            </div>      
            <div class="form_field name_element" id="time-for-container">
                <select name="time_for" id="time_for">
                    <?
                        foreach($users as $key => $u):
                            if($u->userId==$this->session->userdata('userId')):                             
                            ?>
                                <option selected="selected" value="<?=$u->userId?>"><?=$u->userName?></option> <?='\n'?>
                            <?
                            else:
                            ?>
                                <option value="<?=$u->userId?>"><?=$u->userName?></option> <?='\n'?>
                            <?
                            endif;
                        endforeach;
                    ?>
                </select>
                <p id="time-for-error"></p>
            </div>
        </div>      
    <? else: ?>
        <input type="hidden" id="time_for" name="time_for" value="<?=$this->session->userdata('userId')?>">
    <? endif; ?>

<div class="form_row">
  <div class="form_field">
    <label for="hrs_spent">Hours and minutes spent:</label> 
  </div>

  <div class="form_field name_element" id="mins-spent-container">
    <input type="text" maxlength="6" name="hrs_spent" id="hrs_spent" value="" />
            <span id="min-separator">:</span>
            <input type="text" maxlength="6" name="mins_spent" id="mins_spent" value="" />
    <p id="mins-spent-error"></p>
            <p id="hrs-spent-error"></p>
  </div>
</div>

<div class="form_row">
  <div class="form_field">
    <label for="date_worked">Date Worked:</label> 
  </div>

  <div class="form_field name_element" id="date-picker-container">
    <input type="text" name="date_worked" id="date_worked" />
    <p id="date-worked-error"></p>
  </div>
</div>    

<div class="form_row">
  <div class="form_field">
    <label for="timer_description">Description:</label> 
  </div>

  <div class="form_field name_element" id="description-container">
    <textarea name="timer_description" id="timer_description" value=""></textarea>
    <p id="timer-description-error"></p>
  </div>
</div>

<input type="hidden" id="c_id" name="c_id" value="<?=$task->c_id ?>" />
<input type="hidden" id="p_id" name="p_id" value="<?=$task->p_id ?>" />
<input type="hidden" id="t_id" name="t_id" value="<?=$task->t_id ?>" />

<input type="hidden" name="login-folder" id="login-folder" value="<?=base_url()?>login" />
<input type="hidden" name="submit-folder" id="submit-folder" value="<?=base_url()?>times/submit_time" />

<div class="form_row">      
    <div id="message-box"></div>
    <input type="button" name="submit" id="submit_time" class="button-styles button-three" value="Add time" />      
</div>

</div>    

Controller method:

class Times extends MY_Controller { var $options;

    //Ajax function used to submit the time information from task page form.
    function submit_time()
    {
        $options=array();

        $this->form_validation->set_rules("time_for","Time for","trim|required|is_natural_no_zero");
        $this->form_validation->set_rules("hrs_spent","Hrs spent","trim|required|is_natural|min_length[1]|max_length[5]");      
        $this->form_validation->set_rules("mins_spent","Mins spent","trim|required|is_natural|min_length[1]|max_length[2]|less_than[60]");
        $this->form_validation->set_rules("timer_description","Description","trim|min_length[5]|max_length[1000]");
        $this->form_validation->set_rules("date_worked","Date Worked","trim|required|callback__valid_date_format");

//$json->data=array('success'=>0,'validation'=>1,'error'=> validation_errors() );
//$this->load->view('data/json_encode',$json);

        if($this->form_validation->run())
        {
          $options['hrs_spent'] = $this->input->post('hrs_spent');
          $options['mins_spent'] = $this->input->post('mins_spent');            
          $options['timer_description'] = $this->input->post('timer_description');
          $options['date_worked'] = $this->input->post('date_worked');
          $options['t_id'] = $this->input->post('t_id');
          $options['u_id'] = $this->input->post('time_for');//Notice time for field here.

          $add = $this->time_model->add_time($options);

          if(!$add):
            $json->data=array('success'=>0,'validation'=>1,'error'=>'Database error');
          else:
                $json->data=array('success'=>1,'validation'=>1);    
                $this->log_model->add_log_entry( array('log_id'=>1,'item'=>'Time record "'.reduce_string($options['timer_description'],50).'" was added for user '.$options['u_id'].'.') );
            endif;

          $this->load->view('data/json_encode',$json);
        }
        else
        {
          $json->data = array(
            'time_for' => form_error('time_for'),
            'hrs_spent' => form_error('hrs_spent'),
            'mins_spent' => form_error('mins_spent'),           
            'timer_description' => form_error('timer_description'),
            'date_worked' => form_error('date_worked'),
            'success'=>0,
            'validation'=>0,
            'error'=>'There are errors in the form.'
          );

          $this->load->view('data/json_encode',$json);
        }
    }

}

回答1:

The problem is the capitalization used in the callback method name. The method name, and all subsequent references to it as a validation rule, should be all lowercase.

To explain, this is the relevant part of the Form Validation library that causes the message:

if ( ! isset($this->_error_messages[$rule]))
{
    if (FALSE === ($line = $this->CI->lang->line($rule)))
    {
        $line = 'Unable to access an error message corresponding to your field name.';
    }
}
else
{
    $line = $this->_error_messages[$rule];
}

All of your set_message() calls name the rule as _Valid_Date_Format, which is the array key that exists in $this->_error_messages.

Because your rule is defined as _valid_date_format, and because PHP is case-sensitive most of the time, the isset() rule fails, and you clearly don't have a language line defined for it, so it goes to the default.

In general, using capitalization in your controller methods will cause problems. So it's best to avoid doing so.