Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Extending Validation Classs
  • I've read through the Validation class documents on how to extend the validation class and add a new callback, but I'm unclear how to do this when using fieldsets with function set_form_fields() within a model. For example, here's a simplified model:
    class Model_Admin extends Model
    {
      $form->add('first_name',
       'First Name',
       array(
        'type' => 'text',
        'value' => ! empty($admin['first_name']) ? $admin['first_name'] : '',
        'id' => 'first-name',
        'size' => 50,
       ),
       array(
        array('required'),
        array('trim'),
        array('max_length', 50),
       )
      );
    
    // Other form fields and logic
    
    

    Here's the sample callback function inside the extended Validation class:
    class Validation extends \Fuel\Core\Validation
    {
     public function _validation_unique($val, $options)
     {
      list($table, $field) = explode('.', $options);
    
      $result = DB::select("LOWER (\"$field\")")
       ->where("$field", '=', MBSTRING ? mb_strtolower($val) : strtolower($val))
       ->from($table)->execute();
    
      if($result->count() > 0)
       return false;
      else
       return true;
     }
    
    Where and how do I add this callback using fieldset/model?
  • Hey Mitchell, I'm having this same problem when using the fieldset class. Were you ever able to get it to work? - Calvin
  • Yes, I've been able to get it to work. It's been a while now, but I think there were 2 problems. One was that I had the wrong format for adding the new validation function. I was either using the CodeIgniter format or I misunderstood the format. Anyway, here's a short example of adding a new validation function. This adds the function by extending the validation class. You may have to do something different if you add the validation function to the model. I did a lot of cutting and pasting of the code below to try to cut it down to the minimum needed to get the idea. Hopefully, it makes sense and there are no errors. Let me know if something is not clear. BTW, the function _validation_unique() is based on an example from Jelmer. Controller code:
     public function action_add_edit_example($example_id = null)
     {
    ...
      $form = Fieldset::factory('form_example')->add_model('Model_Mexamples', $example_id, 'set_form_fields_example');
    ...
    }
    

    Model code:
    class Model_Mexamples extends Model
    {
     public static function set_form_fields_example(Fieldset $form, $example_id = null)
     {
      if ($example_id != null)
      {
       $data = self::get_example_info($example_id);
      }
    
    ...
    
      $form->add('email',
       'Email',
       array(
        'type' => 'text',
        'value' => ! empty($user['email']) ? $user['email'] : '',
        'id' => 'email',
        'size' => 50,
       ),
       array(
        array('required'),
        array('trim'),
        array('max_length', 255),
        array('valid_email'),
        array('unique', 'auth_users', 'email', 'user_id', $user_id),
       )
      );
    ...
    }
    

    Validation code goes into extended Validation class (don't forget to add to bootstrap.php Autoloader:add_classes array)
     public function _validation_unique($form_value, $db_table, $unique_field, $id_field, $id)
     {
      $query = DB::select($unique_field)
       ->from($db_table)
       ->where("$unique_field", '=', MBSTRING ? mb_strtolower($form_value) : strtolower($form_value))
       ->and_where($id_field, '!=', $id)
       ;
    
      $result = $query->execute();
      if ($result->count() == 0)
      {
       return true;
      }
      else
      {
       $this->set_message('unique', 'That :label is already used. Please pick a different :label.');
       return false;
      }
     }
    
  • Hey Mitchell, How did you extend the Validation class? When I use: class Appvalidate extends Validation I get: ErrorException [ Error ]: Using $this when not in object context This is how I call Appvalidate in my model: $form->validation()->add_callable('Appvalidate');
  • I was able to get the custom validation going, but I still can't extend the validation class (so I can't use methods like set_message()). I'm pretty sure it's a scope problem given that the error is cannot use $this in object context. Also, in case it is helpful to anyone, I added something to validation function unique, a param called $inputs, to check to make sure none of the inputs to be validated are the same value: if(!is_null($inputs))
    {
    unset($inputs);
    if(count(array_unique($inputs)) < count($inputs)) return false;
    }
  • Try extending the validation class like this: class Validation extends \Fuel\Core\Validation Name the file: validation.php Put it in directory: app/classes/ Don't forget to add to bootstrap.php Autoloader:add_classes array
  • Getting closer. Thanks a lot for your help. I think this one might be a bug. If you ran into it, and I might be doing something wrong, I'd appreciate it. Otherwise don't worry about it, I'll track it down. You've helped a ton already: Notice! ErrorException [ Notice ]: Array to string conversion COREPATH/classes/validation/error.php @ line 124: 123:
    124: return $open.str_replace($find, $replace, $msg).$close;
    125: } I get this when using set_message in the extended class.
  • Why don't you post your code for the validation function where set_message() is called.
  • Here's the class being extended: class Validation extends \Fuel\Core\Validation Here's the function and params: public function _validation_unique($val, $table, $field, $inputs = null, $accepted = null) Here's how I'm calling set_message: $this->set_message('unique', 'The field :label must be unique. You cannot use the same name as you have assigned to other tags.');
  • Well what you have looks good to me. Of course, the error is not in set_message(), it's in get_message() when a validation error occurs. You may want to inspect what those variables are at line 124.
  • Thanks, dude! I'll check it out. You've been a great help, I really appreciate it.
  • hello I think you should be able to use unique rule as all others, btut you forget to add the extended class to the fuel/app/bootstrap.php
    like this:
    Autoloader::add_classes(array(
       'Validation' => APPPATH.'classes/validation.php',
    ));
    

    Good luck!
  • I should have mentioned that I did include the following in the bootstrap.php file:
    Autoloader::add_classes(array(
     // Add classes you want to override here
     // Example: 'View' => APPPATH.'classes/view.php',
     'Security' => APPPATH.'classes/security.php',
     'Session' => APPPATH.'classes/session.php',
     'Validation' => APPPATH.'classes/validation.php',
     'Fieldset' => APPPATH.'classes/fieldset.php',
    ));
    

    Also, in trying to simplify the model code, I left out the field where I attempt to call the "unique" function:
      $form->add('username',
       'User Name',
       array(
        'type' => 'text',
        'value' => ! empty($admin['username']) ? $admin['username'] : '',
        'id' => 'phone',
        'size' => 50,
       ),
       array(
        array('required'),
        array('trim'),
        array('max_length', 50),
        array('unique[simpleusers.username]'),
       )
      );
    
    When I run the code, function notice() in error.php is called with msg:
    Invalid rule "unique" passed to Validation, not used.
  • Hijacking this thread: you're the first that I know off that extends a lot of core classes. Any particular reason for this? Extending in Fuel should not be needed unless you want to replace existing methods, in which case I'm interested in the why.
  • I do this too, but I'd rather report my findings in whole then blurt out various bits and pieces on this forum. Although there is one issue in particular that I'd like to address separately but I don't know if I should derail this thread. I'll go and write a new topic now.
  • I'm not sure if you're asking why I'm extending the core classes at all or why I'm not extending them using something like the first example:
    class MyConfig extends Config The reason I'm not extending the core using My... is because I have not been able to get it to work. I'm probably missing something, but what I tried is the following: In app/classes/mysession.php:
    class MySession extends Session
    &#123;
     public static function print_flash()
     &#123;
      $flash = Session::get_flash();
    
      if (isset($flash['success']))
      &#123;
       return '<p class="success">' . Session::get_flash('success') . '</p>';
      }
      else if (isset($flash['notice']))
      &#123;
       return '<p class="notice">' . Session::get_flash('notice') . '</p>';
      }
      else if (isset($flash['error']))
    &#123;
       return '<p class="error">' . Session::get_flash('error') . '</p>';
      }
      else
      &#123;
       return null;
      }
     }
    }
    
    Calls to Session::print_flash() result in an error: Call to undefined method Fuel\core\Session::print_flash(). Please let me know if you see what I'm doing wrong. If your question was why am I extending the core classes at all, you can probably see from the example that I'm basically wrapping the Fuel functionality in a higher level wrapper. All suggestions for better ways to do things are always welcome.
  • Actually nvm for now.
  • @Mitchell, Your app/bootstrap.php needs to contain:
    Autoloader::add_classes(array(
     'Session' => APPPATH.'classes/session.php',
    ));
    

    And your session class extension needs to be defined as
    class Session extends Fuel\Core\Session {
    }
    

    The entire My-business is something CodeIgniter uses. In Fuel, your extended class needs to be called the same as the core class, otherwise you can never overload methods ( which are called via \Session::methodname() ).
  • @WanWizard I've been successfully using the bootstrap.php and autoloader approach to both add new functions and overload core functions, however in the documentation http://fuelphp.com/docs/general/extending_core.html, it describes using the My... approach which I've not been able to get to work. Any thoughts on my original question regarding how to add a validation rule when using fieldsets and a model with the function set_form_fields()? In bootstrap.php:
    Autoloader::add_classes(array(
     // Add classes you want to override here
     // Example: 'View' => APPPATH.'classes/view.php',
     'Security' => APPPATH.'classes/security.php',
     'Session' => APPPATH.'classes/session.php',
     'Validation' => APPPATH.'classes/validation.php',
     'Fieldset' => APPPATH.'classes/fieldset.php',
    ));
    

    In app\classes\validation.php:
    class Validation extends \Fuel\Core\Validation
    &#123;
     public function _validation_unique($val, $options)
     &#123;
      list($table, $field) = explode('.', $options);
    
      $result = DB::select("LOWER (\"$field\")")
       ->where("$field", '=', MBSTRING ? mb_strtolower($val) : strtolower($val))
       ->from($table)->execute();
    
      if($result->count() > 0)
       return false;
      else
       return true;
     }
    

    In app\classes\model\admin.php:
    public static function set_form_fields(Fieldset $form, $user_id = null)
    &#123;
    ....
      $form->add('username',
       'User Name',
       array(
        'type' => 'text',
        'value' => ! empty($admin['username']) ? $admin['username'] : '',
        'id' => 'phone',
        'size' => 50,
       ),
       array(
        array('required'),
        array('trim'),
        array('max_length', 50),
        array('unique[simpleusers.username]'),
       )
      );
    ....
    

    \core\classes\error.php function notice() generates error message: Invalid rule unique[simpleusers.username] passed to Validation, not used.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion