Form Validation Won't Work if Load Two Models - CodeIgniter - php

I have one controller and try to load two models (Usermodel and Contentmodel) and also I need to load Form Validation Library. I use Usermodel to do everything with user such as login and register, and I need Contentmodel to do everything with my web content. At first I was able to login and register and I had no problem with Form Validation Library, but then when I add a line $this->load->model('contentmodel'); to load Contentmodel, I suddenly get this error:
If I remove the line $this->load->model('contentmodel'); everything goes back to normal again.
Controller (Controll.php):
defined('BASEPATH') OR exit('No direct script access allowed');
class Controll extends CI_Controller {
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* #see http://codeigniter.com/user_guide/general/urls.html
*/
public $lang;
public $logo;
public function __construct () {
parent::__construct();
$this->load->helper('url');
$this->load->helper('form');
$this->load->model('contentmodel');
$this->load->model('usermodel');
$this->load->library('session');
$this->load->library('form_validation');
/*get all user sessions data*/
$this->sesi = $this->session->all_userdata();
$config = $this->contentmodel->load_config();
$this->lang = $config['lang'];
$this->logo = $config['image_logo_path'];
$data['lang'] = $this->lang;
$this->load->view('/header/header');
}
public function panel(){
$this->form_validation->set_rules('email', 'Email', 'required');
$this->form_validation->set_rules('cred', 'Password', 'required');
if($this->form_validation->run() === false){
echo '<center style="position: relative;z-index:10000;font-family: \'Roboto\', sans-serif;color:white;top: 62%;">'.validation_errors().'</center>';
$this->load->view('login');
}else{
$user = $this->usermodel->login();
if($user == 0){
echo '<center class="logerror" style="position: relative;z-index:10000;font-family: \'Roboto\', sans-serif;color:white;top: 62%;">Username or Password incorect. Please try again</center>';
$this->load->view('login');
}else{
$data['data'] = 2;
$data['user'] = $user;
$this->load->view('/header/navbar',$data);
$this->load->view('panel');
$this->load->view('/footer/footer');
}
}
}
And also, if I remove/comment these lines:
$this->form_validation->set_rules('email', 'Email', 'required');
$this->form_validation->set_rules('cred', 'Password', 'required');
/* ... */
if($this->form_validation->run() === false){
/* ... */
}else{
/* ... */
}
Everything goes back to normal again as well.
Please help me. Thanks in advance.

The problem is your $lang variable. As you can see, the Form_validation Library is also using it ($this->CI->lang->load('form_validation');) . Change it to something else, and set it to private. As a rule, any variable inside your controller should be set to private, or else you will have such issues.

You produced a strange problem.Your question title Form Validation Won't Work if Load Two Models - CodeIgniter is wrong.
Form validation library does not stop working how many model you load. You need to find what mistake you do.
Your mistake
#CodeGodie already mentioned why you got that error.Little more addition
If you remove this code $this->lang = $config['lang']; from your controller construct function it will work
why?
Codeigniter's controller uses $lang as an object of CI_Lang class.Form validation class uses(look inside the file and the line number that your error message gave) that variable and it should be object of CI_Lang. But you replacing it as string at your controller construct function that's why you got that error.

On your form validation run part you use === try only with ==
`if($this->form_validation->run() === false){`
replace with.
`if($this->form_validation->run() == false){`
Also You have quite a bit in the construct area.
Auto load url and form helper
Don't load a view in __construct area bad practice I think
Controller With Callback
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Controll extends CI_Controller {
public function __construct () {
parent::__construct();
$this->load->helper('url'); // Autoload it
$this->load->helper('form'); // Autoload it
$this->load->library('session'); // Autoload it
$this->load->model('contentmodel');
$this->load->model('usermodel');
$this->load->library('form_validation');
// Removed View From Construct not good idea to have in construct area.
}
// change panel to index.
public function index() {
$this->form_validation->set_rules('email', 'Email', 'required|callback_user_login');
$this->form_validation->set_rules('cred', 'Password', 'required');
if ($this->form_validation->run() == TRUE) {
// You could redirect to another controller once login
redirect('success_page');
}
// http://www.codeigniter.com/userguide2/general/views.html
// If not data pass through these views then you will need to use
// something like $this->load->view('header', null, true);
// or with data $this->load->view('header', $data, true);
$this->load->view('header', null, true);
//$this->load->view('header', $data, true);
$this->load->view('login'); // if you need to pass data through to login page then $this->load->view('login', $data);
$this->load->view('footer', null, true);
//$this->load->view('footer', $data, true);
}
public function user_login() {
$user = $this->usermodel->login();
if ($user == TRUE) {
return TRUE;
} else {
$this->form_validation->run('user_login', 'Incorrect Username Or Password');
return FALSE;
}
}
}
On your view then echo the validation messages
<?php echo validation_errors(); ?>
CI2 http://www.codeigniter.com/userguide2/libraries/form_validation.html
CI3 http://www.codeigniter.com/user_guide/libraries/form_validation.html

Related

Problems extending CI library Form_validation

I have tried to extend the Form_validation library from Codeigniter with no success.
I have two functions that I'd like in this extended class but when the validation is run i get these messages in the log:
DEBUG - 06-07-2016 11:20:33 --> Unable to find validation rule: checkAccountnameForUpdate
DEBUG - 06-07-2016 11:20:33 --> Unable to find validation rule: checkEmailForUpdate
Here is my extended class which is placed in
application/libraries
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
public function __construct($rules = array())
{
// Pass the $rules to the parent constructor.
parent::__construct($rules);
// $this->CI is assigned in the parent constructor, no need to do it here.
}
public function checkAccountnameForUpdate($accountname, $id)
{
return 1;
}
public function checkEmailForUpdate($email, $id)
{
return 1;
}
}
And here's my rules:
$this->form_validation->set_rules('editAccountname', 'Brugernavn', 'required|checkAccountnameForUpdate[hiddenField]');
$this->form_validation->set_rules('editEmail', 'Email', 'required|checkEmailForUpdate[hiddenField]');
$this->form_validation->set_message('checkAccountnameForUpdate', 'Test2');
$this->form_validation->set_message('checkEmailForUpdate', 'Test');
// hiddenField is the name of a hiddenField containing the users ID.
I've googled around and tired some different stuff. I have no idea why it doesn't work.
EDIT 1:
I've tried to replace
$this->form_validation->set_rules('editAccountname', 'Brugernavn', 'required|checkAccountnameForUpdate[hiddenField]');
$this->form_validation->set_rules('editEmail', 'Email', 'required|checkEmailForUpdate[hiddenField]');
to
$this->form_validation->set_rules('editAccountname', 'Brugernavn', 'required|checkAccountnameForUpdate');
$this->form_validation->set_rules('editEmail', 'Email', 'required|checkEmailForUpdate');
No changes.
Here is my extension to the validation library. I have left a few functions out as they are site specific but do not affect the demo here.
APPPATH/libraries/MY_Form_validation.php
class MY_Form_validation extends CI_Form_validation
{
public function __construct($rules = array())
{
parent :: __construct($rules);
}
/*
* reformats the input to ###-###-#### and returns formatted string,
* if it cannot accomplish the format (of a non-empty input) it returns FALSE.
*/
public function phone_format($phone)
{
if(empty($phone))
{
//assume an empty field is OK.
//There needs to be a required rule to check a required field and that rule should
//be before this one in the list of rules
return TRUE;
}
$phone = preg_replace('/[^0-9]/', '', $phone);
$newPhone = preg_replace("/([0-9]{3})([0-9]{3})([0-9]{4})/", "$1-$2-$3", $phone);
if(preg_match('/((\d){3})?(\-){1}(\d){3}(\-){1}(\d){4}/', $newPhone))
{
//preg_replace was able to reformat it to the correct pattern - must be good
return $newPhone;
}
return FALSE;
}
/**
* field validation for zipcode
*/
public function check_zipcode($zipcode)
{
$result = (bool) preg_match("/^([0-9]{5})(-[0-9]{4})?$/i", $zipcode);
return $result;
}
}
We can test this class with the simple controller and view shown below. The test uses the phone_format validator function.
A couple things to note about how I'm using form_validation->set_rules().
First, I pass an array of rules instead of the usually demonstrated pipe separated string. eg. "trim|required". Why? Because set_rules() turns the string into an array anyway so why make it do the extra work?
Second. Notice I am passing a fourth argument. The fourth argument is not well documented. Its use is shown in the Setting Error Messages section but it is not described in the Class Reference section of the documentation. The argument accepts an array of error messages in the form ['rule_name' => 'This is the error message'].
I'm also in the habit of using the short syntax to create arrays eg. $this->data = []; instead of $this->data = array(); mostly because it's less typing.
Here's the test controller Testcase.php
class Testcase extends CI_Controller
{
protected $data;
function __construct()
{
parent::__construct();
$this->data = [];
$this->load->library('form_validation');
}
public function test_validation()
{
$this->form_validation->set_rules('phone', 'Phone'
, ['trim', 'required', 'phone_format']
, [
'phone_format' => 'Not a valid phone number.',
'required' => '<em>{field}</em> required.'
]
);
if($this->form_validation->run() == FALSE)
{
$this->load->view('test_form_v', $this->data);
}
else
{
echo "Passed Validation<br>";
echo $_POST['phone'];
}
}
}
And here is the view file test_form_v.php
<?php
echo form_open('testcase/test_validation');
echo form_input('phone', set_value('phone'));
echo form_error('phone');
echo form_submit('Submit', 'Submit');
echo form_close();
Run it by entering this url in a browser your_doman.whatever/testcase/test_validation
Submit without entering any input and you get the required error. Submit "123456789" and you get the invalid phone number error message. Submit "1234567890" and you get
Passed Validation
123-456-7890
This demonstrates that the extend class and its new validator works. I hope this helps you figure out your problem.

CodeIgniter User is able to copy and paste URL and access main page

I am trying to build a simple login system using CodeIgniter. I have placed all of my functions into one controller and I have also placed a session check function called is_logged_in into the controller. However, the user can still copy and paste the URL once they have logged out and view the main page. It seems like my is logged in function isn't working. Am I missing something? It only works if I place a check in my header every time instead. Here is my code.
Controller file
function index()
{
$this->load->view('login');
}
function checklogin()
{
$this->load->model('user');
$query = $this->user->validate_login();
if($query)
{
redirect('portal/home');
}
else
{
$this->index();
}
}
function logout()
{
$this->session->unset_userdata('username');
$this->session->unset_userdata('is_logged_in');
$this->session->sess_destroy();
redirect($this->index(),'refresh');
}
function is_logged_in()
{
$is_logged_in = $this->session->userdata('is_logged_in');
if(!isset($is_logged_in)||$is_logged_in!=TRUE)
{
$this->index();
}
}
function home()
{
$this->is_logged_in();
$data['main_content'] = 'home';
$this->load->view('includes/template',$data);
}
function statements()
{
$this->is_logged_in();
$data['main_content'] = 'statements';
$this->load->view('includes/template',$data);
}
function about()
{
$this->is_logged_in();
$data['main_content'] = 'about';
$this->load->view('includes/template',$data);
}
}
?>
This is what I place into my headers that actually works instead of the function
<?php
if(!$this->session->userdata('is_logged_in'))
{
redirect('portal/index');
}
?>
User Model
<?php
class User extends CI_Model{
function __construct()
{
parent::__construct();
}
public function validate_login()
{
//$this->form_validation->set_rules('username', 'Username', 'trim|required');
//$this->form_validation->set_rules('password', 'Password', 'trim|required');
$username = $this->security->xss_clean($this->input->post('username'));
$password = $this->security->xss_clean(md5($this->input->post('password')));
$this->db->where('username', $username);
$this->db->where('password', $password);
$query = $this->db->get('accounts');
if($query->num_rows()==1)
{
foreach($query->result() as $row)
{
$sess_data = array(
'username'=>$this->input->post('username'),
'is_logged_in'=>TRUE,
'privilege'=>$row->privilege
);
}
$this->session->set_userdata($sess_data);
return true;
}
else
{
// echo $password;
}
}
}
?>
Also, how can I combine the commented out part in the user model with the next lines? I want an error message to be sent if no input is placed. Hope I can get help with this.
So much wrong in this. Do not, not ever, use a single controller for your application. Things will get pretty big, pretty fast, and then you have one unreadable blob of a file. Keep your application code normalized. That's why you are using MVC. If you then need a method accessible from every, or nearly every controller, then put this function into a base controller(MY_Controller i.e.), or a model, or a library, depending on the functionality of this method. But in your case, this is for a base controller. This wont help with your problem, but just a friendly suggestion.
The problem with your code is, the visitor hits the URL for method "statements" and this is what happens:
statements calls is_logged_in
is_logged_in determines user is not logged in and calls index
index loads the login view
statements method loads the statements view
After you check for log in, and determine that the user is not logged in, you have to prevent further execution of other parts of your code. I would suggest having is_logged_in method returning a bool(false) value, and the statements(and other methods) then stopping execution. But if you would separate your code like you should over multiple controllers, then maybe have the is_logged_in controller to redirect the user to the login page.

codeigniter - pass messages to view

I am new to codeigniter. I have a controller users which loads a login view.
class user extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->helper(array('form'));
}
public function login()
{
$this->load->model('user_images');
$data = $this->load->model('login');
$this->load->view('login', $data);
}
}
In the login model I handle all the validation and processing. If there is a validation error or the like I return $data['msg'] = 'some error message'; I pass this data via $data = $this->load->model('login'); to $this->load->view('login', $data); and in view I echo $msg. However upon submission the form processes, if I enter the correct credentials I get logged in, however if I enter some wrong credentials the validation errors do not get passed to the view. I am moving this project over from an non-framework environment, so I am sure that the validation rules work .etc. I am just not sure why the messages are not getting parsed on the view.
It looks like you are getting this wrong
$data = $this->load->model('login');
The load->model() loads the login_model and makes it methods available via
$this->login->youMethodHere().
f there is a validation error or the like I return $data['msg'] = 'some error message'; I pass this data via $data = $this->load->model('login'); to $this->load->view('login', $data);
When you return something from a method/function you do not return the variable. You return the value of the variable.
You should add you method to the login_model (perhaps this should be user_model...) and return ex. an array or mysqli result set from the model. Depeanding on what the models returns you should set the data.
$this->load->model('user_model');
$login_succes = $this->user_model->login($username, $password);
if( $login_success )
{
$data['msg'] = 'hurrah you did it
...

Codeigniter HMVC MY_Form_validation from library

Whatever I do I cant seem to use the dob function in my MY_Form_validation... please note the _register_verify is inside my User library, and not a controller, so I'm using $CI and not $this...
<?php
/** application/libraries/MY_Form_validation **/
class MY_Form_validation extends CI_Form_validation
{
public $CI;
function __construct( $config = array() )
{
parent::__construct($config);
log_message('DEBUG', 'MY FORM VALIDATION Initialized!!');
}
// --------------------------------------------------------------------
public function dob($dob)
{
$CI =& get_instance();
$CI->form_validation->set_message('dob[]_check', 'Please enter a valid DOB');
show_error('I AM AN ERROR');
}
This is the function in my User Library...
public function _register_verify($testmode = FALSE)
{
if ($testmode) return TRUE;
$CI =& get_instance();
$CI->load->library('form_validation');
$CI->form_validation->CI =& $CI;
$CI->form_validation->set_rules('dob[]', 'DOB', 'trim|dob');
if ($CI->form_validation->run() == FALSE)
{
// What to do if user details are NOT correct?
$CI->session->set_flashdata('dob_error', form_error('dob[]'));
return FALSE;
} else {
return TRUE;
}
}
I'v tried extending the MY_Form_validation and nothing else and it still doesnt work. And most of the turotials i've found call the form_validation from a controller.
I have checked the log and the log message is not there and no error shows.
EDIT: Managed to get the class initialized, however the dob never gets called
Functions inside of MY_Form_Validation.php should return boolean values that give the outcome of the test.
public function dob($dob){
//not perfect, but, returns true if date matches 12/10/1999 for example.
return preg_match("/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/", $dob);
}
Make sure you've set dob as a rule either in you controller, or in your config file, depending on how you've set things up:
$this->load->library('form_validation');
$this->form_validation->set_rules('dob', 'date of birth', 'required|dob');
Errors are handled in application/language/english/form_validation_lang.php. Add:
$lang['dob'] = "Oops, wrong DOB format.";
Lastly, please run your form validations inside your controller, not a library, or model. There is no need to call get_instance() and assign to $CI in this use-case.

Creating a custom codeigniter validation rule

I have a function in my login form that checks if the email and password match the values in the database and if so it logs the user into the system.
I would like to display a validation error if this function returns false.
My problem is that I am unsure how to go about creating this. The message relates to both the password and email fields so I would not want a rule for each input field just display a single message.
I have tried using flashdata to achieve this but it only works when the page has been refreshed.
How can I created a new validation rule solely for the function $this->members_model->validate_member() ??
$this->form_validation->set_error_delimiters('<div class="error">', '</div>');
$this->form_validation->set_rules('email_address', '"Email address"', 'trim|required|valid_email');
$this->form_validation->set_rules('password', '"Password"', 'trim|required');
if ($this->form_validation->run() == FALSE)
{
$viewdata['main_content'] = 'members/login';
$this->load->view('includes/template', $viewdata);
}
else
{
if($this->members_model->validate_member())
{
You use the callback_ in your rules, see callbacks, for ex.
$this->form_validation->set_rules('email_address', '"Email address"', 'trim|required|valid_email|callback_validate_member');
and add the method in the controller. This method needs to return either TRUE or FALSE
function validate_member($str)
{
$field_value = $str; //this is redundant, but it's to show you how
//the content of the fields gets automatically passed to the method
if($this->members_model->validate_member($field_value))
{
return TRUE;
}
else
{
return FALSE;
}
}
You then need to create a corresponding error in case the validation fails
$this->form_validation->set_message('validate_member','Member is not valid!');
One best way to achieve this is extending CodeIgniter’s Form Validation library. Let say we want to create a custom validator named access_code_unique for the field access_code of the database table users.
All you have to do is creating a Class file named MY_Form_validation.php in application/libraries directory. The method should always return TRUE OR FALSE
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation {
protected $CI;
public function __construct() {
parent::__construct();
// reference to the CodeIgniter super object
$this->CI =& get_instance();
}
public function access_code_unique($access_code, $table_name) {
$this->CI->form_validation->set_message('access_code_unique', $this->CI->lang->line('access_code_invalid'));
$where = array (
'access_code' => $access_code
);
$query = $this->CI->db->limit(1)->get_where($table_name, $where);
return $query->num_rows() === 0;
}
}
Now you can easily add your new created rule
$this->form_validation->set_rules('access_code', $this->lang->line('access_code'), 'trim|xss_clean|access_code_unique[users]');

Categories