How can i validate something i did not get from a form. I want to validate my variable and i want this rule to be is_uniqe() to check for duplicates.
I have tried setting a rule in the $rules array as array( 'field' => $this->characterNAME, 'rules' => 'is_unique[members.char_name]) yet no effect i tried calling the is_unique() on its own yet no effect and i tried to asign the variable to $_POST['charNAME'] = $this->characterNAME; and then pass that to set_rules() yet no effect.
How can i validate my variable ?
My code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Registration extends CI_Controller {
var $characterNAME = "";
var $characterCORP = "";
var $characterALLY = "";
var $characterJDAT = "";
function __construct() {
parent::__construct();
$this->load->helper('form');
$this->load->library('form_validation');
$this->load->model('Registration_model', 'reg');
}
public function index()
{
$this->load->view('registration_view');
}
function insert()
{
$rules = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required|min_length[6]|max_length[250]|is_unique[members.username]'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required|min_length[6]|max_length[250]|md5'
),
array(
'field' => 'apiid',
'label' => 'apiid',
'rules' => 'required|integer|min_length[6]|max_length[250]|callback_api_check[' . $this->input->post('apikey') . ']'
),
array(
'field' => 'apikey',
'label' => 'apikey',
'rules' => 'required|min_length[6]|max_length[255]'
),
);
$_POST['charNAME'] = $this->characterNAME;
$this->form_validation->set_rules('charNAME', 'CharacterName', 'is_unique[members.char_name]');
$this->form_validation->set_rules($rules);
if($this->form_validation->run() == FALSE)
{
$this->load->view('registration_view');
} else {
// PROCESS REGISTRATION
$this->reg->add_user($_POST['username'], $_POST['password'], $_POST['apiid'], $_POST['apikey'], $this->characterNAME, $this->characterCORP, $this->characterALLY, $this->characterJDAT);
// REDIRECT
$this->load->view('registration_done');
}
}
function api_check($apiid, $apikey)
{
$url = 'http://api.eveonline.com/account/Characters.xml.aspx?keyID='.$apiid.'&vCode='.$apikey;
$xml = new DOMDocument();
$xml->load($url);
$chars = $xml->getElementsByTagName('row');
foreach ($chars as $character)
{
$charid = $character->attributes;
$curl = 'http://api.eveonline.com/eve/CharacterInfo.xml.aspx?keyID='. $apiid . '&vCode='.$apikey . '&characterID=' . $charid->item(1)->nodeValue;
$cxml = new DOMDocument();
$cxml->load($curl);
$corp = $cxml->getElementsByTagName("corporation");
$ally = $cxml->getElementsByTagName("alliance");
$char = $cxml->getElementsByTagName("characterName");
$jdat = $cxml->getElementsByTagName("corporationDate");
// Check database instead
if($this->reg->validate_entity($corp->item(0)->nodeValue) || $this->reg->validate_entity($ally->item(0)->nodeValue))
{
$this->characterNAME = $char->item(0)->nodeValue;
$this->characterCORP = $corp->item(0)->nodeValue;
$this->characterALLY = $ally->item(0)->nodeValue;
$this->characterJDAT = $jdat->item(0)->nodeValue;
return true;
}
}
$this->form_validation->set_message('api_check','None of the characters on this account are allowed to join.');
return false;
}
}
You can validate that your form input isn't a duplicate by calling the is_unique function directly, via (example):
$this->form_validation->is_unique($email, 'users.email');
This will return a boolean true/false. True = Is Unique -- in this case
Therefore, you can put that in an if() and check it that way...
Hope this helps
Related
Helo, Im new to php and CI. I just following ci tutorial here, and i got problem in this part.
Here is my model
public $rules_admin = array(
'name' => array(
'field' => 'name',
'rules' => 'trim|required'
),
'email' => array(
'field' => 'email',
'rules' => 'trim|required|valid_email|callback__unique_email'
),
'password' => array(
'field' => 'password',
'rules' => 'trim|matches[password_confirm]'
),
'password_confirm' => array(
'field' => 'password_confirm',
'rules' => 'trim|matches[password]'
)
);
This is my controller
function edit($id = NULL)
{
$id == NULL || $this->data['user'] = $this->user_m->get($id);
$rules = $this->user_m->rules_admin;
$id || $rules['password'] .= '|required'; // i have Noticed about this
$this->form_validation->set_rules($rules);
if ($this->form_validation->run() == TRUE) {
}
$this->data['subview'] = 'components/admin_edit';
$this->load->view('components/index', $this->data);
}
public function _unique_email($str)
{
$id = $this->uri->segment(4);
$this->db->where('email', $this->input->post('email'));
!$id || $this->db->where('id !=', $id);
$user = $this->user_m->get();
if (count($user)) {
$this->form_validation->set_message('_unique_email', '%s should be unique');
return FALSE;
}
return TRUE;
}
I have loaded model, helper, library.
I also found 2 comments on video that provide solution, i try it but still not working.
What should i do? Thank you.
define $rules as an array on top of the method
$rules = array();
$rules = $this->user_m->rules_admin;
or
$rules[] = $this->user_m->rules_admin;
No idea with what you trying to archive here $id || $rules['password'] .= '';
If you need to push this to array you can use $rules['password'] = '|required'; (for password)
change
$id || $rules['password'] .= '|required';
to
$id || $rules['password']['rules'] .= '|required';
$rules['password'] is Array . Use String type . Operator, return Notice Message: Array to string conversion
So i have two radio button named Result that have value Fit and Unfit. And one form input that named Detail. If the Unfit is checked then the Detail must be filled. How do i set the validation. currently i have callback function in the controller like this:
public function _is_detail_required()
{
$result = $this->input->post('Result', true);
if ($result != 'Unfit') {
$detail = $this->input->post('Detail', true);
if ($result == 'Unfit') {
$this->form_validation->set_message('_is_detail_required', '%s harus diisi.');
return false;
}
}
return true;
}
and this is the validation rules (on models directory) that i set for the Detail:
$form_rules = array(
array(
'field' => 'Result',
'label' => 'Result',
'rules' => 'trim|xss_clean|required|max_length[50]'
),
array(
'field' => 'Detail',
'label' => 'Detail',
'rules' => 'trim|xss_clean|callback__is_detail_required|max_length[50]'
)
);
my problem is, this callback function is not working. how do i fix this? Any help will be very much appreciated.
You can try to add this in your form validation:
$CI =& get_instance();
if ($CI->input->post('Result') == 'Unfit') {
$form_rules[] = array(
'field' => 'Detail',
'label' => 'Detail',
'rules' => 'trim|xss_clean|required|max_length[50]'
);
}
Note: If your validation is located in your controller, use $this. If not, use $CI =& get_instance(); instead.
The callback function that I wrote is wrong, it didnt check if the input form (Detail) is empty, so this is the correct one
public function _is_detail_required()
{
$result = $this->input->post('Result', true);
if (! empty($result) && $result == 'Unfit') {
$detail = $this->input->post('Detail', true);
if (empty($detail)) {
$this->form_validation->set_message('_is_detail_required', '%s harus diisi.');
return false;
}
}
return true;
}
I'm trying to validate a form in the actual form itself, but it doesn't get validated at all. If I type "someemail&*!([]#gmail.com", it doesn't really give a crap and moves on.
Form:
class RecoverPasswordForm extends Form {
public function __construct($options = null) {
parent::__construct("RecoverPassword");
$username = new Element("username");
$username->setLabel("Email");
$username->setAttributes(
array('filters' => array(
array('name' => 'StringTrim'),
array('name' => 'StripTags')),
'validators' => array(
array(
'name' => 'Regex',
'options' => array(
'pattern' => '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/',
'messages' => array(
Regex::NOT_MATCH => 'The email your provided has invalid characters.',
),
),
'break_chain_on_failure' => true
),
array(
'name' => 'EmailAddress',
'options' => array(
'messages' => array(
EmailAddress::INVALID_FORMAT => "Email address is invalid",
EmailAddress::INVALID => "",
EmailAddress::INVALID_LOCAL_PART => "",
EmailAddress::INVALID_HOSTNAME => "",
EmailAddress::INVALID_SEGMENT => "",
EmailAddress::DOT_ATOM => "",
EmailAddress::INVALID_MX_RECORD => "",
),
),
),
),
'label' => 'Email'));
$this->add(array(
$username,
));
}
}
How I'm getting (or trying to get) the filters and validators in the controller:
public function recoverPasswordAction() {
$this->cache = new Container("cache");
$request = $this->getRequest();
$form = new RecoverPasswordForm();
// $form->get("submit")->setValue("Send mail");
$this->view->form = $form;
if ($request->isPost()) {
$user = new User();
$form->getInputFilter()->getValues();
$form->setInputFilter($form->getInputFilter());
$data = $request->getPost();
$form->setData($data);
$username = $data['username'];
$userData = $this->getServiceLocator()->get("UserTable")->fetchList("`username` LIKE '$username'");
if (!count($userData) > 0) {
$this->cache->error = "A user with this email does not exist, plese try again.";
}
if ($form->isValid()) {
foreach ($userData as $user) {
$user->sendMail(6);
$this->cache->success = "A message has been send to this email, containing your password.";
}
}
}
return $this->view;
}
Try like this...
$request = $this->getRequest();
$form = new Form();
if($request->isPost()) {
if($form->isValid($reguest->getPost())) {
$values = $form->getValues(); //filtered valid array of values
$username = $form->getValue('username');
}
}
$this->view->form = $form;
I think it's because of wrong implementation of validators.
Could you try to implement InputProviderInterface on your form? Basic example is given in the docs. There it is set on an Element, but you can do this on your form too. This interface define getInputSpecification where you have to return an array with filter and validator specification.
I'm new to CodeIgniter and I've been trying to implement a form submitting function, however whenever I press "submit" the form page simply refreshes and the database is not updated! It seems that the $this->form_validation->run() is always returning false, but I have no idea why.
The controller function is as follows:
public function write_prof_review($prof_id)
{
$this->load->model('Queries');
// form stuff here
$this->load->helper('form');
$this->load->library('form_validation');
$data['prof_id'] = $prof_id;
if($this->form_validation->run() == FALSE){
$this->load->view('create_prof_review', $data);
}
else {
$this->Queries->submit_prof_review($prof_id, $this->USERID);
$this->load->view('form_submitted');
}
}
And here is the function submit_prof_review() in the model:
function submit_prof_review($prof_id, $user_id)
{
$data = array(
'course_code' => $this->input->post('course_code'),
'easiness' => $this->input->post('easiness'),
'helpfulness' => $this->input->post('helpfulness'),
'clarity' => $this->input->post('clarity'),
'comment' => $this->input->post('comment')
);
$average = round((($data['easiness'] + $data['helpfulness'] + $data['clarity'])/3),2);
date_default_timezone_set('Asia/Hong_Kong');
$date = date('m/d/Y h:i:s a', time());
$data['average'] = $average;
$data['date'] = $date;
$data['course_id'] = 0;
return $this->db->insert('review_prof', $data);
}
And finally the view for the form (create_prof_review.php):
<h2>Write a review</h2>
<?php echo form_open('home/write_prof_review/'.$prof_id); ?>
<h3>Course code
<input type = 'text' name = 'course_code'></h3>
<h3>Easiness
<input type = 'text' name = 'easiness'></h3>
<h3>Helpfulness
<input type = 'text' name = 'helpfulness'></h3>
<h3>Clarity
<input type = 'text' name = 'clarity'></h3>
<h3>Comment</h3>
<textarea name = 'comment' rows = '4' cols = '50'></textarea>
<br>
<input type = 'submit' name = 'submit' value = 'Submit'>
</form>
Been stuck on this for a couple of days, but I still can't figure out what's wrong. Any help would be greatly appreciated!
I think this is happening because you have not set any validation rules.
Controller code should look like this:
public function write_prof_review($prof_id)
{
$this->load->model('Queries');
// form stuff here
$this->load->helper('form');
$this->load->library('form_validation');
$data['prof_id'] = $prof_id;
// here it is; I am binding rules
$this->form_validation->set_rules('course_code', 'Course Code', 'required');
$this->form_validation->set_rules('easiness', 'easiness', 'required');
$this->form_validation->set_rules('helpfulness', 'helpfulness', 'required');
if($this->form_validation->run() == FALSE) {
$this->load->view('create_prof_review', $data);
}
else {
$this->Queries->submit_prof_review($prof_id, $this->USERID);
$this->load->view('form_submitted');
}
}
Please refer to the CodeIgniter user guide; it will give you more information about validation rules.
I had the same problem though the cause was different. I was missing one of the input fields that I was validating from the form i.e
private function validate_data(){
$validate_data = array(
array(
'field' => 'steps',
'label' => 'Steps',
'rules' => 'trim|required|integer|xss_clean'
),
array(
'field' => 'pace',
'label' => 'Pace',
'rules' => 'trim|required|integer|xss_clean'
),
array(
'field' => 'speed',
'label' => 'Speed',
'rules' => 'trim|required|numeric|xss_clean'
),
array(
'field' => 'distance',
'label' => 'Distance',
'rules' => 'trim|required|numeric|xss_clean'
)
);//end array validate_data
return $validate_data;
}
I was missing the speed input field in the form. I added it and the problem was solved. It really gave me a headache cause I was just reusing code that I have used so many times, so I could not understand why ($this->form_validation->run() was returning false, something that I had never experienced before.
You can go to system/library/Form_validation.php
and in
if (count($this->_config_rules) == 0)
{
return FALSE;
}
change false to true
I can't seem to get my form validation working with Codeigniter. I've tried extending the Form_validation class by creating My_Form_validation.php and have had no success. I'm now trying the callback method. I was getting errors to show up for a little while, however they were incorrect.
This is the code that is located in my controller:
function create_user() {
$this->load->library('form_validation');
$validate = array(
array(
'field' => 'first_name',
'label' => 'First Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'last_name',
'label' => 'Last Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|required|xss_clean|callback_user_exists'
),
array(
'field' => 'email_address',
'label' => 'Email Address',
'rules' => 'trim|required|valid_email|callback_email_exists'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required|min_length[5]|max_length[32]'
),
array(
'field' => 'password2',
'label' => 'Confirm Password',
'rules' => 'trim|required|matches[password]'
)
);
$this->form_validation->set_rules($validate);
if($this->form_validation->run() == FALSE) {
$this->load->view('user/user-signup');
} else {
$this->load->model('user_model');
if($query = $this->user_model->create_user()) {
$this->load->view('user/user-login');
} else {
$this->index();
}
}
}
function user_exists($username) {
$this->load->model('user_model');
$this->user_model->user_exists($username);
$this->form_validation->set_message('user_exists', 'This username is already taken');
}
function email_exists($email) {
$this->load->model('user_model');
$this->user_model->email_exists($email);
$this->form_validation->set_message('email_exists', 'This email is already in use');
}
And this is the code located in my Model:
function create_user() {
$insert_user = array(
'first_name' => $this->input->post('first_name'),
'last_name' => $this->input->post('last_name'),
'username' => $this->input->post('username'),
'email_address' => $this->input->post('email_address'),
'password' => md5($this->input->post('password'))
);
$insert = $this->db->insert('users', $insert_user);
return $insert;
}
function user_exists($username) {
$this->db->where('username', $username);
$query = $this->db->get('users');
if($query->num_rows > 0) {
return true;
} else {
return false;
}
}
function email_exists($email) {
$this->db->where('email_address', $email);
$query = $this->db->get('users');
if($query->num_rows > 0) {
return true;
} else {
return false;
}
}
I'm wanting to validate by checking to see if a Username or Email Address already exists in the database, and if so, the user will need to make the appropriate changes.
Any ideas?
Your code is very hard to read, so I'll show you how improve it. :)
In your controller, you can use constructor for model loading instead this two lines:
$this->load->model('user_model');
Like this:
function __constructor() {
parent::__constructor();
$this->load->model('user_model');
}
Change your user_exists callback to this:
function user_exists($username) {
$user_check = $this->user_model->user_exists($username);
if($user_check > 0) {
$this->form_validation->set_message('user_exists', 'This username is already taken');
return FALSE;
}
else {
return TRUE;
}
}
Change your email_exists callback to this:
function email_exists($email) {
$check_email = $this->user_model->email_exists($email);
if($check_email > 0) {
$this->form_validation->set_message('email_exists', 'This email is already in use');
return FALSE;
}
else {
return TRUE;
}
}
Now, go back to your model and change these two models methods:
function user_exists($username) {
$this->db->where('username', $username);
$query = $this->db->get('users');
return $query->num_rows();
}
function email_exists($email) {
$this->db->where('email_address', $email);
$query = $this->db->get('users');
return $query->num_rows();
}
Now, you do it wrong because you don't understand what model means. in the models methods, you can write database queries... So, if you want to create an user, you should get inputs' information in the controller and then pass them to the model method create_user, like this:
Controller method create_user:
function create_user() {
$this->load->library('form_validation');
$validate = array(
array(
'field' => 'first_name',
'label' => 'First Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'last_name',
'label' => 'Last Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|required|xss_clean|callback_user_exists'
),
array(
'field' => 'email_address',
'label' => 'Email Address',
'rules' => 'trim|required|valid_email|callback_email_exists'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required|min_length[5]|max_length[32]'
),
array(
'field' => 'password2',
'label' => 'Confirm Password',
'rules' => 'trim|required|matches[password]'
)
);
$this->form_validation->set_rules($validate);
if($this->form_validation->run() == FALSE) {
$this->load->view('user/user-signup');
} else {
$user_data['first_name'] = $this->input->post("first_name");
$user_data['last_name'] = $this->input->post("last_name");
$user_data['username'] = $this->input->post("username");
$user_data['email_address'] = $this->input->post("email_address");
$user_data['password'] = $this->input->post("password");
if($query = $this->user_model->create_user($user_data)) {
$this->load->view('user/user-login');
} else {
$this->index();
}
}
}
Model's method create_user:
function create_user($user_data) {
return $this->db->insert("users", $user_data);
}
That's all, it will work. Good luck.
Have you tried is_unique[table_name.field_name] rule?
Example:
$this->form_validation->set_rules('username', 'Username',
'required|min_length[5]|max_length[12]|is_unique[users.username]');
$this->form_validation->set_rules('email', 'Email',
'required|valid_email|is_unique[users.email]');
Update
If you want to use a callback function then user_exists function should be in the controller instead in the model as you mentioned.
The correct way to define is -
public function username_check($str)
{
if ($str == 'test')
{
$this->form_validation->set_message('username_check', 'The %s field can not be the word "test"');
return FALSE;
}
else
{
return TRUE;
}
}
Re-write your function like this
function user_exists($username) {
$this->load->model('user_model');
$result = $this->user_model->user_exists($username);
if($result != NULL){
$this->form_validation->set_message('user_exists', 'This username is already taken');
return FALSE;
}else{
return TRUE;
}
}
You are not returning true or false therefore it is always getting last true returned by xss_clea.
i have had the same problem.
One of the problems with the callback function is that it can only accept one parameter.
there are two states to consider when checking for uniqueness of a record in your form.
1) you are adding a new record
2) you are editing an existing record.
if you are adding a new record the inbuilt is_unique works fine.
if you are editing an existing record is_unique does not work, because it finds the record you are editing and says the form data is not unique.
to get around this problem i have used the session class, set it for case 2 before you run the validation script, so you need to know if you are editing an existing record, or adding a new record. to do this i just add a hidden input to the form when it is edited, eg the records unique id.
presumably you have a unique user id in your users table, eg so set it before the validation is run.
if($this->input->post('user_id')){$this->session->set_userdata('callback_user_id',$this->input->post('user_id'));}
then in your callback, use this sort of algorithm:
case 1) ie $this->session->userdata('callback_user_id') == FALSE
if the user name is unique, validate, and return true.
if the user name is not unique, return false with validation message user has to be unique.
case 2) ie, the callback_user_id is set.
if the user name is unique, validate and return true
if the user name is already set, and that record has the same id as user_id, that means you are updating the same record, and its fine to validate.
otherwise, another record has the username, and it should fail validation.
in the model i just have a method that returns the unique id for a username.
after you run the validation, its probably a good idea to unset the callback_user_id session variable.
i'm sorry i don't have code to paste, but i think this description should help you.
==== edits
nowadays, i think overriding the form validation with a new function is the way to go.
so: have a language pack entry, a form validation line and the override:
This assumes that a field is posted named ID that has the id of the row.
$lang['form_validation_is_unique_not_current'] ='The {field} field must contain a unique value.';
array('field' => 'username', 'label' => 'lang:…username…', 'rules' => 'trim|required|min_length[2]|max_length[40]|is_unique_not_current[users.username]'),
class MY_Form_validation extends CI_Form_validation {
function __construct($rules = array())
{
parent::__construct($rules);
$this->_error_prefix = '<div class="alert alert-danger"><p>';
$this->_error_suffix = '</p></div>';
}
public function is_unique_not_current($str, $field)
{
sscanf($field, '%[^.].%[^.]', $table, $field);
$id = $this->CI->input->post('id');
if($this->CI->input->post('field_name'))
{
return isset($this->CI->db)
? ($this->CI->db->limit(1)->get_where($table, array(
$field => $str,
'id <> ' => $id))->num_rows() === 0)
: FALSE;
}
return FALSE;
}
}