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
...
Related
Currently if i accessed main/subscriber am able to view page when not logged in I have created a function in Main controller -refer to User role page redirect codeigniter for clarity on code.
public function subscriber() {
$this->load->view('header', $data);
$this->load->view('dashboard/subscriber', $data);
$this->load->view('footer');
}
The simplest way to protect your different routes based on user is logged in or not, use a session variable.
when a user logged in in your app then set a sessio variable like this
$this->session->set_userdata('is_logged_in', TRUE);
and check that variable in constructor of a controller so that user is verified before calling any method.
class Demo_controller extends CI_Controller{
public function __construct(){
parent::__construct();
// check if user is logged in
if(!$this->session->userdata('is_logged_in')){
// user is not logged in then redirect user to any page you want
}
}
}
you can also use hooks for creating such system in Codeigniter
You need to protect your pages. Let's assume that your $_SESSION['email'] variable is only set when the user has logged in. We can use that as a flag to determine if the user is logged in.
Add these functions to your User_model (make sure the model is autoloaded).
public function is_logged() {
if (is_null($this->session->userdata('email')) {
redirect('main/login');
exit; // just in case
}
}
public function is_allowed($perm) {
$roles = $this->session->userdata('roles');
if ($roles !== 'admin' && $perm !== $roles) {
// maybe set flashdata so user knows why they were redirected
redirect('main/' . $roles);
exit; // just in case
}
}
Then controller:
class Subscriber extends CI_Controller {
public function construct() {
parent::__construct();
$this->user_model->is_logged(); // can merge with below func, just make sure it is called first (!imp)
$this->user_model->is_allowed('subscriber');
}
public function subscriber() {
$this->load->view('header', $data);
$this->load->view('dashboard/subscriber', $data);
$this->load->view('footer');
}
}
This is as basic as it gets. You can do it more fancy if you wish. I personally use a database-based ACL system.
Also consider renaming roles to just role in your db and elsewhere, it is confusing considering a user only has 1 role (given your previous question).
If you want to prevent user from accessing certain pages if not logged in codeigniter,
you should first set_userdata when login.
Change the controller as below. When session data are not empty it will redirect you to the specific page. Otherwise, 'write what needs to be done'.
public function subscriber()
{
if($this->session->userdata('id')!="")
{
$this->load->view('header', $data);
$this->load->view('dashboard/subscriber', $data);
$this->load->view('footer');
} else {
//your code here
}
}
I have a situation of loosing value stored in $member variable.
class User extends CI_Controller {
protected $message;
function list()
{
$data['message'] = $this->message; // it's empty
$this->load->view('view', $data);
}
function delete($id)
{
$this->user_model->delete($id);
$this->message = "Success";
redirect('user/list');
}
}
The reason of using a redirect is to get a clean URL. I get empty value for $this->message in list() after getting redirected.
I even tried making it static, but still no luck.
You could try using flash messages:
function delete($id)
{
$this->user_model->delete($id);
$this->session->set_flashdata('message', 'Success');
redirect('user/list');
}
For this you are likely to need to load session library in constructor of you controller:
$this->load->library('session');
In your view use this:
<?php echo $this->session->flashdata('message');?>
You can preserve data in flash messages for several requests like this:
$this->session->keep_flashdata('message');
Have a look at this link
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.
I have a gap in understanding Controllers utilization even after visiting the documentation multiple times. I have the following:
class Membership extends CI_Controller
{
/*Load the login view first assuming user is member*/
public function index()
{
$this->load->view('login');
}
/*if not member, load register view*/
public function register()
{
$this->load->view('register');
}
/*view to recover user credentials*/
public function recover()
{
$this->load->view('recover');
}
public function enroll_user()
{
/*Retrieve post parameters*/
$fullname = $this->input->post('fullname');
$email = $this->input->post('email');
$mobile = $this->input->post('mobile');
$home = $this->input->post('home');
$username = $this->input->post('username');
$password = $this->input->post('password');
$confirmPassword = $this->input->post('cpassword');
}
}
now example when user clicked on Register Now link on the main page, the register() function should load the view. But after he completes the form and submit it, to which function should I submit it? Does this mean I have to create two functions per functionality, one to load the view (register.php) and the second one to handle the operation of that function (enroll_user)?
You can do this in just one shot
public function register()
{
$post = $this->input->post();
if($post){
// do other stuff here
// you can load view here too if validation fails
}else{
$this->load->view('register');
}
}
And in you form use this
echo form_open(current_url());
In your register.php put the action of the form to memebership/enroll_user so when the user submits the registration form the action will be submited to enroll_user function and it will take care of the registration etc.
You need two functions, one for displaying the registration form and other for handling the submitted data. You can do it using one controller but its good practice to do it in two controllers because it will be easier for you to find out which function is doing what later.
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]');