EllisLab text mark
Advanced Search
     
Problem extending Form Validation class
Posted: 08 March 2010 08:58 AM
Joined: 2010-01-19
7 posts

Hi guys,

My first post! so be nice!

The issue I am having is with extending the CI_Form_Validation class. I have a few extra validation methods that i need to integrate into my form validation, so thought, rather than using callbacks, i would try and the extend the class….

Now, i believe i have extended the class fine, but when calling any function on the class from my form validation array, it just doesn’t work. It doesn’t pick up the method at all.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class 
MY_Formvalidation extends CI_Form_Validation {
  
  
var $CI;
  
  
/**
   * Contructor
   * Extends core Form Validation class. Sets CodeIgniter super object.
   * @param array $config
   * @author Craig Barber
   * @version 1.0
   */
   
 
function __construct()
  
{
    parent
::CI_Form_Validation();
    
$this->CI =& get_instance();
  
}

  
/**
   * Valid date
   * Checks if input is a valid date.
   * @param string $str
   * @return bool
   * @author Craig Barber
   * @version 1.0
   */
  
function valid_date($str)
  
{
    
if (preg_match('/([0-3][0-9])\/([0-9]{1,2})\/([1-2][0-9]{3})/'$str$date)):
      return 
checkdate($date[2]$date[1]$date[3]);
    else:
      return 
false;
    endif;
  
}
  
  
/**
   * Valid date
   * Checks if input matches a value.
   * @param string $str, string $val
   * @return bool
   * @author Craig Barber
   * @version 1.0
   */
  
function same_as($str$val)
  
{
    
if ($str === $this->CI->input->post($val)) return true;
    else return 
false;
  
}
 
  
  
/**
   * Check num of entries
   * Checks if input matches a value.
   * @param string $str, string $val
   * @return bool
   * @author Craig Barber
   * @version 1.0
   */
  
function check_num_entries($str){
      
if($str >= 4){
        
return true;
    
}else return false;    
  
}
  
  
function checkPayment($str$val){
      
if($this->CI->input->post($val) == 'regular_payments'){
      
//now we need to check whether the payment frequency is set when making regular payments
    
if($str == '0'){
        
//then return false if payment frequency is left blank
        
return false;
    
}else{
        
return true
    
}
  }
}
?> 

Now, I have my form validation in a config array, which sets the validation rules for the whole entire site. This array is stored on a php page named form_validation.php which is held in my config folder. Below is the section for the page which I am trying to write the extra form function for, all the functionality works apart from where i am trying to call my added function named checkPayment.

'payment/create' => array(
    array(
      
'field' => 'nbx_payment_amount',
      
'label' => 'Payment amount',
      
'rules' => 'required|numeric'),
    array(
      
'field' => 'nbx_payment_type',
      
'label' => 'Payment type',
      
'rules' => 'required'),
    array(
      
'field' => 'nbx_payment_date',
      
'label' => 'Payment date',
      
'rules' => 'required|valid_date'),
    array(
      
'field' => 'nbx_payment_number',
      
'label' => 'Number of payments',
      
'rules' => 'required|numeric'),
    array(
      
'field' => 'nbx_payment_frequency',
      
'label' => 'Payment frequency',
      
'rules' => 'checkPayment[nbx_payment_type]')), 

I have tried adding the extended library directly in my controller as seen below:

$this->load->library('MY_Formvalidation'); 

But this doesn’t seem to do anything either, I have also added the library to my autoload file to automatically load the library, no joy there either.

My first question really, is an you extend the CI Form Validation library, and call those extra functions from a validation array? All the examples I have seen on the web do not show this functionality working with a validation array, but setting up the rule in the controller itself (which I have also tried)

Does anyone know of the best way to get around this problem? I’m even residing to the fact that I might have to use callbacks, which is fine, but I couldn’t seem to get that working either!!!

It’s got to the point where I just want a fix….any help welcome!

thanks guys

Craig

 
Posted: 08 March 2010 09:33 AM   [ # 1 ]   [ Rating: 0 ]
Joined: 2009-07-10
32 posts

I’m having exactly the same problem (extending CI_Form_validation breaks the whole library), and haven’t found a solution yet.

Using PHP 5.3.1.

Anyone?

 Signature 

cool smile

 
Posted: 08 March 2010 10:09 AM   [ # 2 ]   [ Rating: 0 ]
Joined: 2009-07-10
32 posts

Update: it seems that CI_Form_validation is nicely initialized when you remove the constructor of your extending class.

 Signature 

cool smile

 
Posted: 08 March 2010 11:22 AM   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2009-03-10
1388 posts
class MY_Form_Validation extends CI_Form_validation {

    
function MY_Form_Validation()
    
{
        parent
::CI_Form_validation();
    
 Signature 

Isset | Isset Public Code Repo | Simple Message Library | Session Profiler for CI2.0 | CI session issues in IE

 
Posted: 08 March 2010 01:26 PM   [ # 4 ]   [ Rating: 0 ]
Joined: 2010-01-19
7 posts

noxie, Piet, thanks for your responses!

I really don’t know what’s going on with this. There must be something that I have set up differently to cause this, because I have tried both the routes you suggested with no success!

My form_validation.php file with my validation array in is loaded in on autoload page. Do I need to load in my newly created extension of the validation class somewhere? or call my function on the extended class directly from my controller?

any help would be great guys! i’m going out of mind, going round in circles on this one!

cheers again

Craig

 
Posted: 08 March 2010 05:03 PM   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2009-12-08
1804 posts

n0xie was pointing out that your file and class should be MY_Form_Validation, not MY_Formvalidation. Also, you should still be loading form_validation… Your class is automatically loaded by CI if it exists.

 Signature 

@basdflasjk | BitAuth: Authentication and Role-based Permissions | Session Library Replacement


Please read the User Guide! (Upgrading from a previous version?)

 
Posted: 08 March 2010 05:19 PM   [ # 6 ]   [ Rating: 0 ]
Joined: 2010-01-19
7 posts

Hey noctrum,

Thanks for posting. Well, i have tried renaming my class to MY_Form_Validation as well, but that still gives me no joy.

Could there be anything else that i am missing, or, in theory, should this work?

thanks

Craig

 
Posted: 09 March 2010 06:04 AM   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2009-03-10
1388 posts

Did you name your file like this?

MY_Form_validation.php 

Also you should autoload the ‘normal’ form_validation library. CI will automagically load you MY_Form_validation.

 Signature 

Isset | Isset Public Code Repo | Simple Message Library | Session Profiler for CI2.0 | CI session issues in IE

 
Posted: 09 March 2010 07:31 AM   [ # 8 ]   [ Rating: 0 ]
Joined: 2009-07-10
32 posts

Still no luck for me.

My extended class system/application/libraries/ci_extend_Form_validation.php:

class ci_extend_Form_Validation extends CI_Form_validation {

    
function ci_extend_Form_Validation()
    
{    
        parent
::CI_Form_validation();        
    
}

In system/application/config/config.php I’ve set

$config['subclass_prefix''ci_extend_'

Very weird.

While debugging some stuff with log_message() and checking my log files, I can confirm that both constructors are being ran (from CI_Form_validation and ci_extend_Form_Validation). But, the CI_Form_validation class just doesn’t work.

EDIT: found some more information.

It seems that the validation rules aren’t loaded when extending the class if you’re using a config file with the rules in it. The rules are loaded from the config file, in the constructor of CI_Form_validation:

function CI_Form_validation($rules = array())
{    
    
/* snip */

    // Validation rules can be stored in a config file.
    
$this->_config_rules $rules;
    
    
/* snip */

But I can’t understand how those rules are passed to the constructor… Anybody?

EDIT: I’ve found the problem cheese  !

The loader class of CI checks for a corresponding config file when loading libraries. This is done at _ci_init_class() in CI_Loader. That all goes well, and the $config array defined at system/application/config/form_validation.php is passed to the extended class, NOT to CI_Form_validation.

So, we need to pass the $config array from our extended class to CI_Form_validation:

class ci_extend_Form_Validation extends CI_Form_validation {

    
function ci_extend_Form_Validation($config)
    
{    
        parent
::CI_Form_validation($config);        
    
}

That ‘fixes’ the problem for me. I can imagine this has to be done for every CI library that ‘supports’ configuration in a file while extending that library (f.e. CI_Email). I’m an experienced developer, but quite a newb at object oriented stuff. So, if anybody has a more decent solution, please post!

 Signature 

cool smile

 
Posted: 10 March 2010 11:53 AM   [ # 9 ]   [ Rating: 0 ]
Joined: 2010-01-19
7 posts

thePiet!!

Good work mate, I have fixed it too!!

You’re right, i don’t know why i didn’t think of that! The extended class obviously needs the config array containing our validation rules to be able to reference to our newly created functions!!

Also, I hadn’t been COMPLETELY strict with my naming. The CI default form validation class is actually ‘Form_validation’ where I was extending ‘Form_Validation’

Drat, blast, christ and all the other swears under the earth!!! haha, you have released a lot of stress and anger!

cheers the Piet, at least we learned the hard way on extending CI classes eh?

PS, your OOP looks fine on your construct ; )

cheers again everyone!

Is there a way to solve this thread or close it?

 
Posted: 17 March 2010 04:51 PM   [ # 10 ]   [ Rating: 0 ]
Joined: 2009-07-10
32 posts

Lol thank you BarberCraig. Don’t know if there’s any way to solve / close a thread, maybe prepend [Solved] or something to the thread title.

Cheers!

 Signature 

cool smile

 
Posted: 09 July 2010 08:04 PM   [ # 11 ]   [ Rating: 0 ]
Joined: 2010-07-09
9 posts

I have the same problem and I’ve already tried your solution, but it doesn’t works yet. I’m using HMVC extension with CI 1.7 (last released) & php 5.3, I don’t have any idea if that affects.

This is MY_Form_validation.php

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class 
MY_Form_validation extends CI_Form_validation{
    
    
function MY_Form_validation($config = array()){
        parent
::CI_Form_Validation($config);
        
$this->_config_rules $config;
        
log_message('debug''MY_Form_validation extensión de clase - inicializada');
    
}
    
        
/*
          this is the function that I added for the callback's in HMVC
        */
    
function run($module ''$group ''){
        log_message
('debug''Se ejecuta función para [CALLBACK] '.$module.' - '.$group);
        (
is_object($module)) AND $this->CI =& $module;
        return 
parent::run($group);
    
}

    
function mysql_date($str){
        log_message
('debug''Se ejecuta la función *****');
        
$pattern '^([1-3][0-9]{3,3})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$';
        
$this->set_message('mysql_date'"%s contains an invalid response");
        return 
preg_match($pattern$str);
    
}
}
/* End of file MY_Form_validation.php */
/* Location: ./system/application/libraries/MY_form_validation.php */ 

And my rule

$this->form_validation->set_rules('Datos[altahacienda]','Alta Hacienda''mysql_date'); 

on my log file, the debug message of the function that validates mysql format date, doesn’t appears, it seems that the function never is called.

 
Posted: 12 March 2012 10:56 PM   [ # 12 ]   [ Rating: 0 ]
Joined: 2012-03-12
1 posts

#### me for having this figured out but here’s the thing it really really works with MVHC and CI 2.0 or higher

check @ http://basics.testro.nl/#post10

thing is you need to throw away the CI_Form_validation stuff

for exact reasons and theory go to my blog

for a working Form_validation class copy this code

<?php
if (!defined(‘BASEPATH’)) exit(‘No direct script access allowed.’);

class Form_validation{

private $CI;

function __construct()
{
$this->CI =& get_instance();
$this->CI->load->library('session');
}
}
?>

name it form_validation.php in your library and check that you the library is loaded in your function construct

But better go to my blog to figure the whole thing out as i also like some comments on where i’m going wrong with my thoughts about it if not i think it’s ok since i don’t take myself too serious as a write and actor, maybe musician as well. How about programming. you don’t want to know i guess

gr,

Robbert

 
Posted: 14 June 2012 11:51 AM   [ # 13 ]   [ Rating: 0 ]
Joined: 2012-06-14
1 posts

Hi…
Been having some trouble extending the form validation library (and other libraries as well).
My setup is a bit different and that may be why! The directory tree is as follows:

-ci (root dir)
|-system (ci’s system files)
|-shared (a shared package containing models, helpers, libraries…)
|-api (an application directory)
|-admin (another app dir)
|-client (yet another app dir)

In the three app config files I’m autoloading the shared package.
In the shared package I’m extending the form validation library (to add extra validation rules/methods).

IF the class extension is located inside one of the apps’ library dir, CI’s loader loads it (as expected) and things run smoothly.
HOWEVER, if the extension class is placed inside the shared library dir, CI does NOT load it, and loads CI’s BASE form validation class instead!

After pulling half my hair (the remaining half).. I found the problem to be from the _ci_load_class() method in the Loader class.
The method ONLY looks for library extensions inside the app’s library dir:

$subclass APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
... 

which actually should be all the possible library paths (app & package(s)):

foreach ($this->_ci_library_paths as $path)
{
   $subclass 
$path.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
   ...

I changed it and it’s working as expected now!

Isn’t this a bug in the Loader class, or is there another (better) way to accomplish what I’m trying to do?

PS. I’m using PHP >5.3 running CI 2.1.0.