Codeigniter & HMVC - Callback not working - codeigniter

I've pretty much gone through a lot of link and solutions provided here and other locations, but I am just not able to solve the callback issue that I am facing. I'm using Codeigniter with HMVC the code is below.
The following code is from My_Form_validation.php:
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = ''){
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
Below if the Callback function :
public function _unique_email($str) {
// Check if user already exists
// Process only for current user
$id = $this->uri->segment(4);
$this->db->where('email', $this->input->post('email'));
!$id || $this->db->where('id !=', $id);
$user = $this->mdl_admin_users->get();
if (count($user)) {
$this->form_validation->set_message('_unique_email', 'User already exists. Please check %s.');
return FALSE;
}
return TRUE;
}
and the function :
public function user_edit($id = NULL) {
// Fetch a user or set a new one
if ($id) {
$data['user'] = $this->mdl_admin_users->get($id);
count($data['user']) || $data['errors'][] = 'User could not be found';
}
else {
$data['user'] = $this->mdl_admin_users->get_new();
}
// setup the form
$rules = $this->mdl_admin_users->rules_admin;
$id || $rules['password'] = '|required';
$this->form_validation->set_rules($rules);
//process the form
if ($this->form_validation->run($this) == TRUE) {
$data = $this->mdl_admin_users->array_from_post(array('firstname', 'lastname', 'email', 'password'));
$data['password'] = $this->mdl_admin_users->hash($data['password']);
$this->mdl_admin_users->save($data, $id);
redirect('admin/user');
}
// Load the view
$data['title'] = 'Edit Users';
$data['module'] = 'admin';
$data['header_file'] = 'header_admin';
$data['nav_file'] = 'nav_admin';
$data['view_file'] = 'edit_users';
$data['footer_file'] = 'footer_admin';
echo Modules::run('template/base_template', $data);
}
Would be a great help if someone could point me at the right direction to resolve the issue. Thanks in advance
Naveen

According to wiredesignz,
When using form validation with MX you will need to extend the CI_Form_validation class as shown below,
/** application/libraries/MY_Form_validation **/
class MY_Form_validation extends CI_Form_validation
{
public $CI;
}
before assigning the current controller as the $CI variable to the form_validation library. This will allow your callback methods to function properly.
class Xyz extends MX_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('form_validation');
$this->form_validation->CI =& $this;
}
}
This will remove HMVC related callback problem without any changes to your code.

First of you are missing in the rules
$rules['email'] = 'required|callback__uniqueemail';
Also call back function should be not like this callback__unique_email for some reason I found codeigniter call back not like extra gap this better callback__uniqueemail
If private do not work make public function removing underscore
public function uniqueemail() // no need $str
When make public do not for get to remove extra underscore from here callback_uniqueemail
Another thing with echo Modules run best to be loaded from view only.
In your controller replace echo Modules run with $this->load->view();
You need to add $this->form_validation->run($this) add $this to run after create library below.
And Create a new library
<?php
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = '') {
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
Tutorial Best https://www.youtube.com/watch?v=8fy8E_C5_qQ

Related

Extended Form_validation library in codeigniter, cannot check is field is empty

I was trying to extend codeigniter(3.1.11) form_validation library to add validation rules of my own.
Below is the code written in application/libraries/MY_Form_validation.php.
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
protected $CI;
public function __construct($rules = array())
{
parent::__construct($rules);
// Assign the CodeIgniter super-object
$this->CI =& get_instance();
}
public function snExists($sn){
if (empty($sn)) {
$this->CI->form_validation->set_message('snExists', '{field} is required');
return FALSE;
}else{
$query = $this->CI->db->query("SELECT `sn` FROM `employee` WHERE `sn` = '$sn';");
$numrows = $query->num_rows();
if ($numrows > 0) {
return TRUE;
}else{
$this->CI->form_validation->set_message('snExists', '{field} does not exist');
return FALSE;
}
}
}
}
The issue i am facing is that, when i submit the field empty the validation does not return FALSE.
somehow the if(empty($sn)) is not satisfied and the else is executed.
hope someone could help. Thank you.
So it looks like codeigniter does not call any validation methods if a field is submitted empty. It will just returns TRUE by default. So in my case checking whether $sn is empty is pointless.

call another controller from dashboard using template pages

I working on Codeigniter project, I create page template to load header left menu and footer, everything working good, when I try the open link in the menu I want to open another controller. I do it but when the controller view open the variable inside to load database table for each row not working.. but the controller who load the database when I open it without my template its working fine
The Dashboard controller
class Dashboard extends CI_Controller{
protected $data = array();
function __construct()
{
parent::__construct();
$this->data['pagetitle'] = 'Invoices Manager';
}
protected function render($the_view)
{
$this->data['the_view'] = (is_null($the_view)) ? '' : $this->load->view($the_view,$this->data, TRUE);
$this->load->view('templates/master_page', $this->data);
}
public function home() {
// $this->load->view('templates/master_page', $this->data);
$this->render( 'templates/homepage_view');
}
public function dashboard() {
// $this->load->view('templates/master_page', $this->data);
$this->render( 'dashboard/home');
}
public function purchaselist(){
$this->render('purchase/index');
}
}
The purchase controller that working good alone
class Purchase extends CI_Controller{
protected $data = array();
protected $mydata = array();
function __Construct()
{
parent::__Construct ();
$this->load->database(); // load database
$this->load->model('Purchase_model'); // load model
$this->mydata['purchase']=null;
}
public function index()
{
$query = $this->Purchase_model->getPurchaselist();
if($query)
{
$mydata['purchase'] = $query;
}
$this->load->view('purchase/index', $mydata);
// $this->render( 'purchase/index');
}
}
when I call dashboard/purchaselist they say the
Message: Undefined variable: purchase
Filename: purchase/index.php
Line Number: 17
its should load database table inside the template
try using dashboard/index.php/purchaselist or load your modal $this->load->model('Purchase_model'); as global
Please pass null or empty array in purchase if $query is empty
public function index()
{
$query = $this->Purchase_model->getPurchaselist();
if(!empty($query)){
$mydata['purchase'] = $query;
}else{
$mydata['purchase'] = array();
}
$this->load->view('purchase/index', $mydata);
// $this->render( 'purchase/index');
}

Codeigniter tidying up my controllers

I've followed Codeigniter's configuration straight out of the manual - and just wondered if there was a simpler or more efficient way of coding my controllers...
eg.
class Home extends CI_Controller {
public function index()
{
$this->load->helper('segment1');
$this->load->model('segment1/Leftsidebar_model');
$data['articles'] = $this->Leftsidebar_model->articles();
$this->load->model('segment1/Default_model');
$data['head'] = $this->Default_model->segment1();
$data['segment1'] = $this->Default_model->segment1();
$data['segment2'] = $this->Default_model->segment2();
$this->load->model('Rightsidebar_model');
$data['coming_up'] = $this->Rightsidebar_model->coming_up();
$data['featured_pages'] = $this->Rightsidebar_model->featured_pages();
$data['recommended_link'] = $this->Rightsidebar_model->recommended_link();
$data['testimonials'] = $this->Rightsidebar_model->testimonials();
$this->load->view('head_view', $data);
$this->load->view('header_view', $data);
$this->load->view('segment1/__leftSidebar_view', $data);
$this->load->view('segment1/__mainContent/default_view', $data);
$this->load->view('segment1/__mainContent/segment2_view', $data);
$this->load->view('__rightSidebar_view', $data);
$this->load->view('footer_view', $data);
}
}
helpers and models can be auto loaded, this can be specified in the confiq file. This will save you from having to manually load them.
As for the rest:
You can subclass CI_Controller. Eg:
My Controller extends CI controller and this would then contain a 2 methods
1) to load page head and header
2) to load page bottom
you could then subclass your controller from My_Controller and call those methods
load_page_top();
//insert whatever you have to load
load_page_bottom();
other than that the rest is up to you
Eg:
class Home extends MY_Controller
{
index()
{
$data = get_data();
load_page_top();
//insert your views here specific to the controller
load_page_bottom();
}
get_data()
{
//gather all your needed data here and return it as an array
return data;
}
}
I love this structure, clean and neat.
class Home extends CI_Controller {
public function index()
{
// Load libraries, helpers, models
$this->load->helper('segment1');
$this->load->model('segment1/Leftsidebar_model');
$this->load->model('segment1/Default_model');
$this->load->model('Rightsidebar_model');
// Data for views
$data = array(
'articles' => $this->Leftsidebar_model->articles(),
'head' => $this->Default_model->segment1(),
'segment1' => $this->Default_model->segment1(),
'segment2' => $this->Default_model->segment2(),
'coming_up' => $this->Rightsidebar_model->coming_up(),
'featured_pages' => $this->Rightsidebar_model->featured_pages(),
'recommended_link' => $this->Rightsidebar_model->recommended_link(),
'testimonials' => $this->Rightsidebar_model->testimonials()
);
// Load views
$this->load->view('head_view', $data);
$this->load->view('header_view', $data);
$this->load->view('segment1/__leftSidebar_view', $data);
$this->load->view('segment1/__mainContent/default_view', $data);
$this->load->view('segment1/__mainContent/segment2_view', $data);
$this->load->view('__rightSidebar_view', $data);
$this->load->view('footer_view', $data);
}
}
Of course, the view loading could be managed in other way, having a view loading all common sections.
I just write little additional library for rendering similar page blocks.
Something like this:
class Display_Lib{
private $_CI;
private $_template_data;
public function __construct()
{
$this->_CI =& get_instance();
}
public function set($key, $value)
{
$this->_template_data[$key] = $value;
}
public function get($key)
{
return $this->_template_data[$key];
}
public function get_template_data()
{
return $this->_template_data;
}
public function display_page($view, $data = array())
{
$this->set('content', $this->_CI->load->view($view, $data, TRUE));
$this->_CI->load->view('templates/main_template', $this->get_template_data());
}
}
Set this library in auto load:
$autoload['libraries'] = array('session', 'database', 'display_lib');
And call it in controller:
class Main extends CI_Controller{
public function index()
{
$some_data = array();
$this->display_lib->display_page('views/main_view', $some_data);
}
}

CodeIgniter routing issue, advice how to do it

I'm not CI programmer, just trying to learn it. Maybe this is wrong approach, please advice.
my controller(not in sub directory) :
class Users extends CI_Controller {
function __construct() {
parent::__construct();
}
public function index($msg = NULL) {
$this->load->helper(array('form'));
$data['msg'] = $msg;
$this->load->view('user/login' , $data);
}
public function process_logout() {
$this->session->sess_destroy();
redirect(base_url());
}
}
And a route for login :
$route['user/login'] = 'users/index';
Problem is when I wanna logout, it shows me 404 because I do not have it in my route :
$route['user/process_logout'] = 'users/process_logout';
and in my view I put logout
When I add that, it works, and that is stuppid to add a route for everything. What I'm I doing wrong, please advice.
Thank you
Don't know why you are trying to implement login feature in index() function. However since you said you are learning CI I'm telling something about _remap() function.
Before that. You can try the following routing:
$route['user/:any'] = 'users/$1';
$route['user/login'] = 'users/index';
If you want to take value immediately after controller segment you need to use _remap() function and this function may be solve your routing problem, i mean you don't need to set routing. Lets implement your code controller 'users' using _remap() function.
class Users extends CI_Controller {
private $sections = array('login', 'logout');
function __construct() {
parent::__construct();
}
public function _remap($method)
{
$section = $this->uri->segment(2);
if(in_array($section, $this->sections))
call_user_func_array(array($this, '_'.$section), array());
else show_404(); // Showing 404 error
}
private function _login()
{
$msg = $this->uri->segment(3);
$this->load->helper(array('form'));
$data['msg'] = $msg;
$this->load->view('user/login' , $data);
}
public function _logout() {
$this->session->sess_destroy();
redirect(base_url());
}
}

Variable inside function __construct() in Codeigniter

I am using Tank_auth for user authentication in codeigniter. To check if any user is logged in or not, if he is then to get the username and id I need to use the following code in every functions of my controllers, which is very irritating.
// If any user is logged in get his/her userid or name
if ($this->tank_auth->is_logged_in()) {
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
}
So , I was wondering if I could make life easier by putting the following code inside the function __construct() like following,
but its not working.
Could you please tell me how to get it work?
Thanks in Advance :)
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
if ($this->tank_auth->is_logged_in()) {
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
}
}
if you plan to use this array only inside this controller, you can use it like this:
//outside the functions define the $data as controller class property:
private $data = array();
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
if ($this->tank_auth->is_logged_in()) {
$this->data['user_id'] = $this->tank_auth->get_user_id();
$this->data['username'] = $this->tank_auth->get_username();
}
}
//and then use it like
function index(){
$this->load->view("something.php",$this->data);
}

Resources