I've created custom validation library class MY_Form_validation as MY_Form_validation.php in application/libraries as follows.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation {
public function __construct($rules = array()) {
parent::__construct($rules);
}
public function file_required($file) {
if($file['size']===0) {
$this->set_message('file_required', 'Uploading a file for %s is required.');
return false;
}
return true;
}
}
?>
In my validation function I've included following rules as follows.
public function validate() {
$this->load->library('form_validation');
$config = array(
array(
'field' => 'name',
'label' => 'Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'display_photo',
'label' => 'Display Photo',
'rules' => 'trim|good|file_required|xss_clean'
),
);
$this->form_validation->set_rules($config);
if ($this->form_validation->run()) {
return true;
}
return false;
}
The core validation rules are working fine but custom rule is not working. So please help me to get the soultion and Its literally wasting my time. The work would be more appreciated.
As far as i understand your function always return true. Because of $file Not $_FILES
public function file_required($file) {
if($_FILES[$file]['size']===0) {
$this->set_message('file_required', 'Uploading a file for %s is required.');
return false;
}
return true;
}
Check the rules in the function validate()
What I think it's incorrect:
$config = array(
array(
'field' => 'name',
'label' => 'Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'display_photo',
'label' => 'Display Photo',
'rules' => 'trim|good|file_required|xss_clean'
),
);
What I think is correct:
$config = array(
array(
'field' => 'name',
'label' => 'Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'display_photo',
'label' => 'Display Photo',
'rules' => 'trim|file_required|xss_clean'
),
);
I think good is not a php function, or an internal codeigniter function.
Edit:
What about using:
if ($file['size'] == 0) {
Instead of
if ($file['size'] === 0) {
Using === means the value MUST BE integer 0, but if $file['size'] returns 0 as string the if won't be true, and the function always will return true.
I had the same problem and found the cause while looking in CodeIgniter's source code. It seems the writers thought that if a field didn't have "required", then it would just skip all the rules and always return that the form has validated. See it for yourself from their code:
// If the field is blank, but NOT required, no further tests are necessary
if ( ! in_array('required', $rules) AND is_null($postdata))
However, if you add "callback_" in front of your rule, you can still make it run, for the procedure, look here:
https://www.codeigniter.com/userguide2/libraries/form_validation.html#callbacks
Related
I've taken the "auth" controller and copied it and renamed it as "site". I have renamed the references to views etc. to "site". When I go to www.mysite/index.php/site/create_user the form loads fine. However on hitting submit I get redirected to www.mysite.com/index.php/site/login and nothing is added to the database. Can anyone tell me why this does not work? My site controller is below:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Site extends CI_Controller {
//
//Authentication
//
function __construct()
{
parent::__construct();
$this->load->database();
$this->load->library(array('ion_auth','form_validation'));
$this->load->helper(array('url','language'));
$this->form_validation->set_error_delimiters($this->config->item('error_start_delimiter', 'ion_auth'), $this->config->item('error_end_delimiter', 'ion_auth'));
$this->lang->load('auth');
}
//Function to log the user in
function login()
{
$this->data['title'] = "Login";
//validate form input
$this->form_validation->set_rules('identity', 'Identity', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == true)
{
// check to see if the user is logging in
// check for "remember me"
$remember = (bool) $this->input->post('remember');
if ($this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember))
{
//if the login is successful
//redirect them back to the home page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect('/', 'refresh');
}
else
{
// if the login was un-successful
// redirect them back to the login page
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect('site/login', 'refresh'); // use redirects instead of loading views for compatibility with MY_Controller libraries
}
}
else
{
// the user is not logging in so display the login page
// set the flash data error message if there is one
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->data['identity'] = array('name' => 'identity',
'id' => 'identity',
'type' => 'text',
'value' => $this->form_validation->set_value('identity'),
);
$this->data['password'] = array('name' => 'password',
'id' => 'password',
'type' => 'password',
);
$this->_render_page('site/login', $this->data);
}
}
//Function to log the user out
function logout()
{
$this->data['title'] = "Logout";
// log the user out
$logout = $this->ion_auth->logout();
// redirect them to the login page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect('site/login', 'refresh');
}
//Function to create a user
function create_user()
{
$this->data['title'] = "Create User";
if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
{
//redirect('site/login', 'refresh');
}
$tables = $this->config->item('tables','ion_auth');
// validate form input
$this->form_validation->set_rules('first_name', $this->lang->line('create_user_validation_fname_label'), 'required');
$this->form_validation->set_rules('last_name', $this->lang->line('create_user_validation_lname_label'), 'required');
$this->form_validation->set_rules('email', $this->lang->line('create_user_validation_email_label'), 'required|valid_email|is_unique['.$tables['users'].'.email]');
$this->form_validation->set_rules('phone', $this->lang->line('create_user_validation_phone_label'), 'required');
$this->form_validation->set_rules('company', $this->lang->line('create_user_validation_company_label'), 'required');
$this->form_validation->set_rules('password', $this->lang->line('create_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[password_confirm]');
$this->form_validation->set_rules('password_confirm', $this->lang->line('create_user_validation_password_confirm_label'), 'required');
if ($this->form_validation->run() == true)
{
$username = strtolower($this->input->post('first_name')) . ' ' . strtolower($this->input->post('last_name'));
$email = strtolower($this->input->post('email'));
$password = $this->input->post('password');
$additional_data = array(
'first_name' => $this->input->post('first_name'),
'last_name' => $this->input->post('last_name'),
'company' => $this->input->post('company'),
'phone' => $this->input->post('phone'),
);
}
if ($this->form_validation->run() == true && $this->ion_auth->register($username, $password, $email, $additional_data))
{
// check to see if we are creating the user
// redirect them back to the admin page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect("site", 'refresh');
}
else
{
// display the create user form
// set the flash data error message if there is one
$this->data['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
$this->data['first_name'] = array(
'name' => 'first_name',
'id' => 'first_name',
'type' => 'text',
'value' => $this->form_validation->set_value('first_name'),
);
$this->data['last_name'] = array(
'name' => 'last_name',
'id' => 'last_name',
'type' => 'text',
'value' => $this->form_validation->set_value('last_name'),
);
$this->data['email'] = array(
'name' => 'email',
'id' => 'email',
'type' => 'text',
'value' => $this->form_validation->set_value('email'),
);
$this->data['company'] = array(
'name' => 'company',
'id' => 'company',
'type' => 'text',
'value' => $this->form_validation->set_value('company'),
);
$this->data['phone'] = array(
'name' => 'phone',
'id' => 'phone',
'type' => 'text',
'value' => $this->form_validation->set_value('phone'),
);
$this->data['password'] = array(
'name' => 'password',
'id' => 'password',
'type' => 'password',
'value' => $this->form_validation->set_value('password'),
);
$this->data['password_confirm'] = array(
'name' => 'password_confirm',
'id' => 'password_confirm',
'type' => 'password',
'value' => $this->form_validation->set_value('password_confirm'),
);
$this->_render_page('site/create_user', $this->data);
}
}
//Function to render the page
function _render_page($view, $data=null, $returnhtml=false)//I think this makes more sense
{
$this->viewdata = (empty($data)) ? $this->data: $data;
$view_html = $this->load->view($view, $this->viewdata, $returnhtml);
if ($returnhtml) return $view_html;//This will return html on 3rd argument being true
}
}
This exact code works when in the auth controller. When in the site controller I make it so you must login and you must be an admin to make a user (i.e. uncommenting out this line //redirect('site/login', 'refresh');) then it also works, but for some reason when that line is commented it works in the auth controller but not the site controller.
Any help is much appreciated. I've tried to figure it out but can't see why it works in one and not the other (and why it works in site but only as an admin when that code is uncommented and not at all when it is commented, whilst in auth it works in either case).
Thanks in advance.
The reason you get redirected is one of two reasons.
First : $this->_render_page('site/login', $this->data);
When you hit the submit button it is still pointing to the login controller.
Second : if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
The create user function in the Auth controller is for admins only, You will have to // out the code or you will be redirected to the login page due to not being logged and not being an admin.
try this:
//$this->_render_page('site/login', $this->data);
//if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
By marking out these two lines you should be able to veiw and submit your page without being redirected.
:)
I am using CodeIgniter 2.3.1 and created a form_validation.php file in config and the content is as below.
<?php
$config = array(
array(
'field' => 'firstname',
'label' => 'First Name',
'rules' => 'required'
),
array(
'field' => 'lastname',
'label' => 'Last Name',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required|valid_email|callback_unique_email'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required|matches[confirm_password]'
),
array(
'field' => 'confirm_password',
'label' => 'Confirm Password',
'rules' => 'required'
)
);
function unique_email($email) {
if($email == 'm#gmail.com') {
$this->form_validation->set_message('unique_email', 'Hello World !');
return false;
}
}
?>
And checking the form_validation in register function of user controller. The code is below.
public function register() {
$this->load->helper('form');
$data['message'] = '';
if($this->input->post('submit')) {
$this->load->library('form_validation');
if($this->form_validation->run() == FALSE) {
$data['message'] = 'User could not be saved.';
} else {
$user_data['firstname'] = $this->input->post('firstname');
$user_data['lastname'] = $this->input->post('lastname');
$user_data['email'] = $this->input->post('email');
$user_data['password'] = md5($this->input->post('password'));
if($this->user_model->insert($user_data)) {
if($this->user_model->login($user_data)) {
$this->session->set_flashdata('message', 'User saved successfully.');
redirect('/user', 'refresh');
}
}
}
}
$this->load->view('user/register', $data);
}
But I am not getting validation message for the custom method. Please suggest me how to do it?. The work is more appreciated.
Have a look at the following documentation: http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#callbacks
As you can see int the documentation, the custom validation function actually belongs in the controller, and not in the config file. By moving the validation function to the controller, the callback function should start getting called.
Another fun fact, people can access this unique_email function through a url (ie. http://yoursite.com/index.php/user/unique_email). To avoid this, we can write the function as a private function by simply placing an underscore at the beginning of the function, like so:
function _unique_email($email) {
...
}
You can then call the function in your validation by using the new function name in your config (notice the extra underscore in the callback:
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required|valid_email|callback__unique_email'
)
In the end, your controller should look similar to the following:
class User extends CI_Controller {
public function register() {
$this->load->helper('form');
$data['message'] = '';
if($this->input->post('submit')) {
$this->load->library('form_validation');
if($this->form_validation->run() == FALSE) {
$data['message'] = 'User could not be saved.';
} else {
$user_data['firstname'] = $this->input->post('firstname');
$user_data['lastname'] = $this->input->post('lastname');
$user_data['email'] = $this->input->post('email');
$user_data['password'] = md5($this->input->post('password'));
if($this->user_model->insert($user_data)) {
if($this->user_model->login($user_data)) {
$this->session->set_flashdata('message', 'User saved successfully.');
redirect('/user', 'refresh');
}
}
}
}
$this->load->view('user/register', $data);
}
function _unique_email($email) {
if($email == 'm#gmail.com') {
$this->form_validation->set_message('unique_email', 'Hello World !');
return false;
}
}
}
Your config would look similar to the following:
$config = array(
array(
'field' => 'firstname',
'label' => 'First Name',
'rules' => 'required'
),
array(
'field' => 'lastname',
'label' => 'Last Name',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required|valid_email|callback__unique_email'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required|matches[confirm_password]'
),
array(
'field' => 'confirm_password',
'label' => 'Confirm Password',
'rules' => 'required'
)
);
I used this answer and got error:
Unable to access an error message corresponding to your field name.
In function _unique_email instead set_message('unique_email', 'Hello World !'); should be set_message('_unique_email', 'Hello World !'); like this:
function _unique_email($email) {
if($email == 'm#gmail.com') {
$this->form_validation->set_message('_unique_email', 'Hello World !');
return false;
}
}
I have 3 fields in my form - lets say A, B, and C. I want to set the validation rules to where if fields A and B are empty then require C. Otherwise, require A and B.
I looked up some material on this and basically I found that I can use a callback function, but I'm a little new to CodeIgniter and I can't quite figure out the syntax to write this out.
A callback is the cleanest way to handle this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class YourController extends CI_Controller {
public function save()
{
//.... Your controller method called on submit
$this->load->library('form_validation');
// Build validation rules array
$validation_rules = array(
array(
'field' => 'A',
'label' => 'Field A',
'rules' => 'trim|xss_clean'
),
array(
'field' => 'B',
'label' => 'Field B',
'rules' => 'trim|xss_clean'
),
array(
'field' => 'C',
'label' => 'Field C',
'rules' => 'trim|xss_clean|callback_required_inputs'
)
);
$this->form_validation->set_rules($validation_rules);
$valid = $this->form_validation->run();
// Handle $valid success (true) or failure (false)
}
public function required_inputs()
{
if( ! $this->input->post('A') AND ! $this->input->post('B') AND $this->input->post('C'))
{
$this->form_validation->set_message('required_inputs', 'Either A and B are required, or C.');
return FALSE;
}
return TRUE;
}
}
this is simple
function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$post_data = $this->input->post();
$this->form_validation->set_rules('A', 'FieldA', 'required');
$this->form_validation->set_rules('B', 'FieldB', 'required');
if(!isset($post_data['A']) AND !isset($post_data['B']))
{
$this->form_validation->set_rules('C', 'FieldC', 'required');
}
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('success');
}
}
You can do it this way as shown below, if you place the set_rules in an if construct you may have problems when you are trying to repopulate using form helpers.
function index()
{
$required='';
if(isset($this->input->post('A')) && isset($this->input->post('B')))
{
$required='required';
}
$this->form_validation->set_rules('A', 'FieldA', 'required');
$this->form_validation->set_rules('B', 'FieldB', 'required');
$this->form_validation->set_rules('C', 'FieldC', $required);
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('success');
}
}
<? if ( ! defined('BASEPATH')) exit();
class Registration extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('registration_model');
}
public function index() {
$this->load->library('form_validation');
$this->form_validation->set_rules('email', 'E-mail', 'trim|required|valid_email|callback_email_available');
if($this->form_validation->run() == FALSE) {
$this->load->view('registration');
} else {
$this->registration_model->add_user();
}
}
# Check E-mail
public function email_available($email) {
$this->db->select('email');
$this->db->where('email', $email);
$query = $this->db->get('users');
$result = $query->row();
if(!empty($result)) {
$this->form_validation->set_message('email_available', 'This e-mail belongs to another user.');
return FALSE;
} else {
return TRUE;
}
}
}
?>
I have a registration form with Form Validation.
And I have a callback function to validate email uniqueness.
All code works fine, but I can directly access to callback function with errors
examle.com/registration/email_available
A PHP Error was encountered
Severity: Warning
Message: Missing argument 1 for Registration::email_available()
Filename: controllers/registration.php
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: email
Filename: controllers/registration.php
How can I deny direct access to callback function?
You can prefix the method name with an _ to deny access through HTTP request.
My suggestion is to tuck your validation rules into a separate file. CodeIgniter supports this by allowing you to save validation configurations in config/form_validation.php. Take a look at the Form Validation Documentation, specifically the section labelled Saving Sets of Validation Rules to a Config File.
Your controller's index:
public function index() {
$this->load->library('form_validation');
if($this->form_validation->run('submit_registration') == FALSE) {
$this->load->view('registration');
}
else{
$this->registration_model->add_user();
}
}
config/form_validation.php
$config = array
(
'submit_registration' => array
(
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'trim|required|valid_email|email_available'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required|alpha_numeric|etc'
)
),
'some_other_submission' => array(
array(
'field' => 'somefield',
'label' => 'SomeField',
'rules' => 'some|rules'
),
array(
'field' => 'getit',
'label' => 'Get The Point?',
'rules' => 'trim'
)
)
);
libraries/MY_Form_validation.php
class MY_Form_validation extends CI_Form_validation
{
function __construct($config = array()){
parent::__construct($config);
}
function email_available($email){
$CI =& get_instance();
//check your database with the $CI variable...
if(email_exists) return TRUE;
else return FALSE;
}
}
I've been struggling with this for the last hour or so, wondering if some fresh eyes can help.
Model
class User extends AppModel {
public $name = 'User';
public $validate = array(
'email' => array(
'valid' => array(
'rule' => 'email',
'message' => 'The email is not valid'
),
'required' => array(
'rule' => 'notEmpty',
'message' => 'Please enter an email'
)
)
);
}
Controller
class UserController extends AppController {
var $uses = array('User');
function index(){
$users = $this->User->find('all');
$this->set(compact('users'));
}
public function add() {
$this->set('title_for_layout', 'Add new user');
if(isset($this->data) && !empty($this->data)) {
$this->User->set($this->data);
$this->log($this->User->invalidFields(), "debug");
if($this->User->validates()){
if ($this->User->save($this->data)) {
$this->Session->setFlash("Added " . $this->data['User']['name']);
$this->redirect('index');
}
} else {
$this->Session->setFlash('There are errors with your form submit, please see below.');
}
}
}
}
View
<?php
echo $this->Form->create('User');
echo $this->Form->input('name', array('label' => 'Name'));
echo "<div class='clear'></div>";
echo $this->Form->input('email', array('label' => 'Email'));
echo "<div class='clear'></div>";
echo $this->Form->button('Reset', array('type' => 'reset'));
echo $this->Form->button('Add Useer', array('type' => 'submit'));
echo $this->Form->end();
?>
But I never get invalid fields for email? Have I missed something glaring?
If it makes any difference, this is a plugin Im developing so it doesnt sit directly in app/ but in app/Plugins
Thanks
EDIT: So I've been struggling with this for a while now, and still no joy. One thing I have noticed though, when I print out the model details (using var_dump($this->User) ), the [validate] array is empty. For example:
[validate] => Array
(
)
[validationErrors] => Array
(
)
Im presuming this is what the issue is, even though I have declared my $validate array, its somehow being overwritten? Anyone come across this before? Any solutions?
public $validate = array(
'email' => array(
'valid' => array(
'rule' => array('email'),
'message' => 'The email is not valid'
),
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please enter an email',
'allowEmpty' => false
)
)
);
Try adding rules as array and adding 'allowEmpty' key set to false on the required validation.
Damn! So simple. If I read the cookbook properly at http://book.cakephp.org/1.3/en/view/1114/Plugin-Models it would have told me that
If you need to reference a model within your plugin, you need to include the plugin name with the model name, separated with a dot.
Thus..
var $uses = array('Plugin.User');
works.. Hope this helps someone else!