I’m this is my first CI Project and I am trying to build a login system (3 user groups = admin, member, public). I’m using Ion Auth.
If you want to skip the details..
..my problem is that I am somehow not doing my “require_once” correctly in my home controller, or I am not understanding something about extending classes. Or I am just not as clever as my mom tells me I am. I get this error:
Fatal error: require_once() [function.require]: Failed opening required 'application/Application/Core/public_controller.php' (include_path='.:/Applications/MAMP/bin/php/php5.3.6/lib/php') in /Applications/MAMP/htdocs/NOIR_FINAL/application/controllers/public/home.php on line 4
I referenced this article, as it looks like good practice. Specifically, I extended CI_Controller with MY_Controller (containing an Admin, Member, and Public controllers that all extended CI_Controller).
http://jondavidjohn.com/blog/2011/01/scalable-login-system-for-codeigniter-ion_auth
Then I saw some criticism of “packing” all these 3 admin, member, and public controllers into one “MY_Controller” .. so as per Phil Sturgeon I have tried to separate them into individual classes and use __autoload() to pull them in.
http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-Base-Classes-Keeping-it-DRY
But somehow I get the feeling that I am now just making things unnecessarily complicated.
I want to go through the login, and then depending on the user group send them to one of 3 “home” controllers in dedicated folders. Those home controllers extend Admin_controller, Member_controller, or Public_controller … and each one of those extends MY_Controller, which in turn extends CI_Controller. So I would have group specific methods in their respective controllers, and some general stuff in MY_Controller ( checking to see if site is live/”open” .. checking user agent .. etc). This, to me, seems to be a pretty nice way of separating user roles.
I also have this in my config, as per Sturgeon’s article ..
function __autoload($class)
{
if(strpos($class, 'CI_') !== 0)
{
@include_once( APPPATH . 'core/'. $class . EXT );
}
}
So am I going about this right way at all? Since its my first try at this and I am starting to think this is becoming a bit too “Frankenstein”. Here is ‘auth/login’…
function login() {
if($_POST) { //clean public facing app input
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == true)
{
$identity = $this->input->post('email', true);
$password = $this->input->post('password', true);
$remember = $this->input->post('remember');
if($this->ion_auth->login($identity,$password, $remember))
{
if($this->ion_auth->in_group('1'))
{
$this->session->set_flashdata('message','Welcome');
redirect('admin/home','refresh'); // this might have to change @todo
}
elseif($this->ion_auth->in_group('2'))
{
$this->session->set_flashdata('message','Welcome');
redirect('member/home','refresh');
}
else
{
redirect('public/home','refresh');
}
}
}
else
{
// set error flashdata
$this->session->set_flashdata('message','Your login attempt failed.');
redirect('/');
}
}
redirect('/');
}
.. and here is home.php in “controllers/member/” .. basically just setting up the view and translating the flashdata message (if any) into $data{‘message’]
class Home extends Member_Controller{
require_once(APPPATH.'Application/Core/member_controller.php');
public function __construct()
{
parent::__construct;
}
public function index()
{
// remember that $this->the_user is available in this controller
// as is $the_user available in any view I load
$this->load->model('Member_model');
$this->data['message'] = $this->session->flashdata('message');
$this->data['query'] = $this->Member_model->get_members();
$this->data['title'] = 'Home';
$this->load->view('member_view', $this->data);
}
}
Here is my member controller with some member methods
class Member_Controller extends MY_Controller{
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->load->view('member_view');
}
public function edit_profile(){}
public function delete_profile(){}
}
.. and MY_Controller with some common methods
class MY_Controller extends CI_Controller {
protected $the_user;
public function __construct()
{
parent::__construct();
if( $this->config->item('site_open' ) === FALSE)
{
show_error("Sorry the site is shut right now.");
}
if( $this->ion_auth->logged_in() )
{
$this->the_user = $this->ion_auth->user()->row();
$data->the_user = $this->the_user;
$this->load->vars($data);
}
else
{
redirect('/','refresh');
}
//if the user is using a mobile, use a mobile theme
$this->load->library('user_agent');
if( $this->agent->is_mobile() )
{
$this->template->set_theme('mobile'); // what about admin @todo
}
}
public function index()
{
redirect('/','refresh');
}
}
So am I approaching this correctly? As a bonus question, is it correct to put index methods on classes that are only ever going to be extended? For ex, nobody is going to “land” on MY_Controller. It will always be extended. So do I need to put an index method? Is it just good form? Should I make this an abstract class?
When it comes to working with require/include, you need to specify the
PATHand it has to be either absolute or relative.Absolute:
relative:
or
if a
PATHis not defined in therequireorinclude, the system will use the include path which is defined inphp.iniWhat you have set:
require_once('application/Application/Core/public_controller.php')will not work because you aren’t setting a relative nor an absolutePATHtherefore the system is looking forpublic_controller.phpin theinclude_pathwhich is set inphp.ini.All this and we haven’t even started in to why you’d be including your public controller in the first place.
When you extend a class, you are making it available as an adjunct to existing classes. As such, when you extend
CI_Controller, sinceCI_Controlleris already available in the application, the extended functionality will be available as well without needing to include the file.No, you don’t need to create an
indexmethod inMY_Controller.Lastly, I don’t know that you need to be doing all this… Extending the core classes is usually reserved for adding some functionality that you may need or is missing to the core or for overriding existing functionality. What you are doing is moving code that would live just fine in controllers into the core application. I supposed it will work, but I don’t think it’s best practice nor very practical.