Controllers for Frontend and Backend in CodeIgniter
Sarfraz Ahmed April 21, 2015 03:10 PMI find it very inconvenient when you need to create all frontend and backend controllers without having any common functionality. I don't like the face that I always have to extend CI_Controller
for all my backend and frontend controllers. I need ability to specify which controllers are related to frontend and which ones relate to backend .
So instead of doing this:
class someFrontendController extends CI_Controller {}
class someBackendController extends CI_Controller {}
I should be able to do this:
class someFrontendController extends FrontendController {}
class someBackendController extends BackendController {}
I also need ability to specify common controllers that can be applicable to both frontend and backend:
class someCommonController extends CommonController {}
I will explain benefits of having such controllers below. But for now, how do we do that ? Well CodeIgniter is very flexible and does allow you to achieve just that.
Extending CodeIgniter's CI_Controller
Class
In order to have separate controllers for backend, frontend and common controllers, please follow these steps:
1) Make sure that config $config['subclass_prefix']
is set to MY_
in application/config.php file. It should be so by default.
2) Create a file called MY_Controller.php in application/core folder and paste this code in it:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
class CommonController extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
}
class FrontendController extends CommonController
{
public function __construct()
{
parent::__construct();
}
}
class BackendController extends CommonController
{
public function __construct()
{
parent::__construct();
}
}
Now for all of your controllers that belong to frontend, you would extend FrontendController
instead of CI_Controller
and for all of your controllers that belong to backend, you would extend BackendController
instead of CI_Controller
like I mentioned above:
class someFrontendController extends FrontendController {}
class someBackendController extends BackendController {}
And for any controllers that might share common data for frontend and backend, you would extend CommonController
:
class someCommonController extends CommonController {}
What's the Point ?
You might already have guessed the benefits of having separate controllers but if you haven't yet, well here they are:
- You can now easily distinguish which controllers belong to backend and which ones belong to frontend
- You now have ability to have common code for both sides of an application.
By common code, I mean any functionality that you would want to be shared in all of your controllers. Let's assume that we have created login functionality and user is logged on frontend. Now normally you would write some code in all of your controllers (for authorized pages for example) that would check whether or not user is logged in; if user is not logged in, redirect him back to login page something like:
class MyController extends CI_Controller
{
public function index() {
// check if user is logged in
$this->checkLoginStatus();
// more code of controller when user is logged in
}
// redirect user to login page if not logged in
protected function checkLoginStatus() {
if (! $this->session->userdata('is_logged_in')) {
redirect('login');
}
}
}
Now for all of your pages that can be viewed only when user is logged in, you will need to insert checkLoginStatus()
function in all of those controllers and then call it index()
function. That's not good, it is repeating code. Remember the rules Don't Repeat Yourself (DRY) and Keep It Simple, Stupid! (KISS) :)
Let's KISS it; simply put checkLoginStatus()
function code in your FrontendController
and now all controllers that extend it will have this login check functionality:
class FrontendController extends CommonController
{
public function __construct()
{
parent::__construct();
// check if user is logged in
$this->checkLoginStatus();
}
// redirect user to login page if not logged in
protected function checkLoginStatus() {
if (! $this->session->userdata('is_logged_in')) {
redirect('login');
}
}
}
And now you don't need to do anything in your normal frontend controllers. You now get login check functionality out of box. In the similar fashion, you can have some common functionality for all of your backend controllers by putting some code in BackendController
. This was just an example for login check but of course you could have some other requirement that you wanted to inject in all of your controllers by using FrontendController
or BackendController
.
You might ask, you could have done all of this by may be using CI Hooks or may be traits, well that's true but I believe having separate controllers gives you more control and separation of concerns.
Similarly, you could put whatever code you want in class for CommonController
that would be applicable to both frontend and backend. For example you could setup application's overall configuration, upload paths, logos, etc whatever you think should be available site-wide; in all controllers of backend and frontend.
So anything that you put in FrontendController
will be available in all controllers of frontend that extend it. Anything that you put in BackendController
will be available in all controllers of backend that extend it. Anything that you put in CommonController
will be available in all controllers of frontend + backend.
And finally there is one more problem I don't like personally. Even though we can now easily find out which controllers belong to frontend or backend, we still have to put all of them in application/controllers folder. This doesn't easily tell by looking at file names which controllers belong where unless you open it up and see what it extends
. Of course we could use prefix for controller file names like front-foo-controller.php
or backend-bar-controller.php
but still you have to put them in same folder. It would have been cool if you could have folder structure like this where you can go any nested level while having each distinct part of functionality in its own module:
+ frontend + module-one + controllers - controllers-one.php - controllers-two.php + models - model-one.php - model-two.php + views - view-one.php - view-two.php + module-two + module-three + backend + module-one + module-two + module-three
Oh yes you can do that as well with the help of HMVC module for CodeIgniter :)
Note: HMVC is not just about organizing folders, it is whole concept where you get ability to have one controller call some other controller. In HMVC, Each model-view-controller triad represents distinct piece of functionality or mini application which runs independent from other triads.
Have fun!