Hi I'm working on a application that uses a admin environment and a user environment. To make my code and controllers more readable I would like to use some kind of a prefix for my admin and user controllers. Or maybe use a different directory for the admin en user controllers. Without using the exact name in the url to call the controllers.
Does anybody know if there is a way to do this or a work around for my idea.
For example I would like to use: user.[controllername].php or user_[controllername].php
EDIT:
So when I use routes to separate the user controllers from the admin controllers, it brakes my template resolver.
For instance lets say the url is: http://myapplication.com/user/profile in normal cases this would call the user controller and the function profile. My template resolver looks for the folder user and checks if there is a level1.tpl file.
Lets say we want to edit this profile the url would be: http://myapplication.com/user/profile/edit/1 now it would search in the folder user for a level2.tpl file and would call the function edit with id 1.
The problem with the routes is that it prepends something to the url witch I don't want because then it searches in the wrong folder for instance when we use admin/dashboard it will look in the folder admin instead of the folder dashboard.
So basically what I only need is only to tell the application to use a different directory where the controllers are located or a different filename base on what kind of user is logged in.
Thanks in advance, for sharing you knowledge.
You can do that in many ways.
1. Create two file in application/core named "Admin_Controller.php" and "User_Controller.php" with following class signature,
class Admin_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
}
and
class User_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
}
In these classes you can do use your PHP logic to do whatever you wants, just simply extends your Controllers to Admin_Controller or User_Controller.
eg: class Home extends User_Controller {} or class Dashboard extends Admin_Controller {}
2. You can also simply do that with routes.php
eg:
// for admin
$route['admin/(.+)'] = 'admin_$1';
// for frontend
$route['(.+)'] = 'user_$1';
I hope this might give you some idea.
Related
I'm currently working on CI for my website, and i'm having some trouble about extending Controller_CI.
I have one controller that deals with login/signin actions, which doesn't need authentication, and others controllers that check if a user session exists before loading content.
For that purpose, I created MY_Controller class and add authentication code in the constructor.
Then I made all my controller extend MY_Controller, except the first one that still extends Controller_CI
My question is : Is it the right way to deals with authentication ? Is it still possible to use Controller_CI even if it's extended ?
I found another pattern :
http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-Base-Classes-Keeping-it-DRY
I guess it's better, but still, I don't understand why not using the first solution.
Thanks
Extending controller class for that purpose will work, but this solution is not much flexible. I would rather create a library that handles authentication, and run it from a controller when it is desired. Please read http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html for details about creating custom libraries in CI.
Please remember you can only extend the CI_Controller with MY_Controller only once. In that aspects it's not a good idea. Suppose you want to implement another feature (e.g. a piece of code that makes a specific entry in the log) for some controllers, but not necessarily the controllers that need authentication you cannot make another MY_Controller.
Using a library is a better thing.
I'm using the flexi auth library on a big CI site. On every controller that requires authentication I just add the following:
public function __construct() {
parent::__construct();
$this->load->library('flexi_auth');
if (!$this->flexi_auth->is_logged_in())
redirect('auth/login');
}
I think a combination of what Phil Sturgeon suggests in that blog post and using a library would be best. So I would create a core controller (by that I mean a controller you place into application/core that extends CI_Controller) called MY_Controller which will look something like this
class MY_Controller extends CI_Controller
{
function __construct()
{
parent::__construct();
}
//Any other functions you want
}
Then judging by your question you currently have controllers that fit into two categories
Controllers that do require a logged in user before they do
anything
Controllers that don't require a logged in user before they do anything
So I would then create another controller in the /application/core directory that extends MY_Controller but in its constructor it checks to see if the user is logged in
class Auth_Controller extends My_Controller
{
function __construct()
{
parent::__construct();
//Check to see if the user is logged in
$this->load->library('authentication');
if(!$this->authentication->user_logged_in())
{
redirect('/login');
}
}
//Any other functions you want
}
Now when you create you controller you can choose which one of the core controllers you want to extend. If its a controller than doesn't require a logged in user you can extend MY_Controller but if it does required a logged in user you can extend Auth_Controller. That way it means you only need to do the user login check once in your code.
Like others have said if may be a good idea to place any authentication code into a library as that's a better place to put it than in a controller.
Summary
So to summarise by having all of your controllers extend core controllers rather than CI_Controller it should cut down on code repetition.
I also currently working on a CI project and had the same issue. I have came up with a different solution to deal with the authentication.
I extended the core controller as bellow,
class MY_Controller extends CI_Controller
{
public $data = array();
public $calledClass ;
public $calledMethod ;
public function __construct()
{
parent::__construct();
$authException['authentication']['login'] = true;
$authException['authentication']['logout'] = true;
$authException['welcome']['index'] = true;
$this->load->library("router");
$this->calledClass = $this->router->fetch_class();
$this->calledMethod = $this->router->fetch_method();
if(!#$authentication[$this->calledClass][$authentication->calledMethod] && !Auth::isUserLoggedIn())
{
# IS_AJAX is a contant defined in the contants.php
# define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(IS_AJAX)
{
# if this is an AJAX call, it sets a value in the header ,
# which can be captured in the AJAX response
# to redirect the user to the login page.
$this->output->set_header("auth-him:1");
exit;
}
else
{
redirect("authentication/login");
}
}
}
}
Hope the code above is clear and this helps.
To extend core controller more than one time, If you still need to use 2 controllers to handle authentication, I have followed this method
https://stackoverflow.com/a/22125436/567854
Hope this also helps :)
In my application I have got a main controller in which I have a few methods. One of them checks if the user is logged in and if not it redirects the user to login form etc.
class FA_Controller_Auth extends Zend_Controller_Action {
public function preDispatch() {
//chceck user is login
}
}
aand all controllers extend from this main class
IndexController extends FA_Controller_Auth{}
but now I am building multi payment gatwey from Zend_Payment_Controllerso Payment_GatewayController should extend from Zend_Payment_Controller. But I need to chack if the user is logged in or not and I am looking for somthing like multi extend
Payment_GatewayController extends Zend_Payment_Controller, FA_Controller_Auth
I know there is no way to use multi extend class in PHP but maybe there is a better way to do this, action helper or plugin to check authorisation ?
Regards.
Regards.
You can only extend one class. This is exactly why using a base controller class is considered bad practice, as it limits you somewhat. Instead you should move the logic for both checks into controller plugins instead.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
CodeIgniter authentication + user privileges
I had 5 user type and have permission table in which i give differnt permission to different user . permission like is_view,is_delete,is_add etc . User access the feature according to these permission.
I complete Database. I want to check the permission given to user on each page before the controller is called.
You should either place your auth-logic in the constructor of the controller
OR
in the constructor of a base-controller (more DRY as you don't have to repeat the logic in all controllers).
I would create a new controller which extends the core controller. Place this file in application/core/
class MY_AuthController extends CI_Controller {
public function __construct() {
// Do your auth check in here, redirect if not logged in
}
}
Then all the pages that need authentication you just inherit this new controller. This file you just place in your regular controller-folder
class Admin extends MY_AuthController {
// All your controller goodness in here..
}
I advise you to read the following two articles:
1. Phil Sturgeon's post on Keeping It Dry.
Phil will introduce you to how to create parent controllers whose constructors will contain the session and potentially database logic. All controllers that you create thereafter should inherit from your custom controllers instead of the native CI_Controller.
Followed by....
2. Shane Pearson's CodeIgniter Base Classes Revisited.
Shane's article revamps Phil's technique and relocates your custom controllers from /core to /base and also utilizes a better __autoload()'er. This implementation allowed me, for instance, to use CodeIgniter's CLI class, whereas, Phil's bugged out.
To give you an idea - your code would look a little something like this once complete:
In /base/MY_In_Controller.php:
<?php
class MY_In_Controller extends CI_Controller{
function __construct(){
parent::__construct();
//things like:
//is the user even logged in? thank heavens I don't have to check this in every controller now. redirect if the session doesnt exist.
//query the database and grab the permissions for the user. persist them with $this->load->vars();
$this->data['perms'] = some_database_function();
$this->load->vars($this->data);
}
}
In controllers/manage.php:
<?php
class Manage extends MY_In_Controller{
function __construct(){
parent::__construct();
}
function index(){
$this->load->view('manage');
//and I can still access their permissions here and in the view.
print_r($this->data['perms']);
}
}
So, i have some problem.
I just want to create some website where visitor can interact with my site if they're registered.
Let say they've provided their username,email,password, blah..blah..blah...
And then after they provided their blah..blah..blah.. it will autologin (if their data is passed) to my site.
After they logged in my site, they must provided more data again, like they uploaded their profile picture, how they control their privacy in my site, like step by step registration.
I don't want they interact with my site, until they complete their registration.
How do i make every page in my site looks like registration page until they finished their registration.
It's not like i will give this kind of function right.
if(is_login()){
if(is_registration_complete()){
//you're free to go
} else {
// complete your registration first
}
} else {
//you're not logged in
}
In my every controller, if you know what I mean :)
How do I create this function globaly?
If their registration isn't complete, they will go to registration controller, in every routes.
If they complete their registration, they will go to the, yeah you know the default routes.
I'm so sorry if my English is bad, English isn't my native language, sorry for grammar mistakes :)
The easiest is probably to create a library with your checking function and then to include it in the Constructor of the impacted ControllerS :
class Blog extends CI_Controller {
public function __construct()
{
parent::__construct();
// Load the lib here or Autoload
$this->load->library('mylogincheckhelper');
$this->mylogincheckhelper->is_complete();
}
}
And then you do all the ckecks and routing in the Lib.
create a view with your post-registering stuff and make them conditionally visible. and include the view in your templates.
One way you can do it is to create a custom controller by extend the core CI_Controller. Then you can have your page controllers extend from your custom controllers. By extending, you inherit the functions of the parent, as well as run the parent constructor (or run it if you override it), making them "globally available" to whoever extends it.
//extend the core controller
class MY_Controller extends CI_Controller {
//override to provide additional functionality
public function __construct(){
//run the core controller
parent::__construct();
//then do your login and registration checks here
//you can put code here, call another function or load a helper class
//or better, redirect them to your registration page
}
}
//your page's controller extending from your custom controller
class Page extends MY_Controller {
//not overriding the constructor will execute the parent constructor
//every page that extends your extended controller will inherit it's functions
//and execute it's constructor
}
actually i am looking to handle my website/admin panel withing same application. so i want to know that is that possible?
i means structure something like this
http://www.mysite.com
and for admin
http://www.mysite.com/admin
so this all i need to handle withing one application of codeignitor. i don't want two codeignitor installation for this purpose.
Sure, you can, see the section at CI docs which says:
Running Multiple Applications with one CodeIgniter Installation
You can also create separate folders for your controllers, models and views like:
+controllers
+front (main site controllers will go here)
+admin (admin controllers will go here)
+models
+front (main site models will go here)
+admin (admin models will go here)
+views
+front (main site views will go here)
+admin (admin views will go here)
See the section:
Organizing Your Controllers into Sub-folders
First Create a base controller for the front and/or backend. Something like this:
// core/MY_Controller.php
/**
* Base Controller
*
*/
class MY_Controller extends CI_Controller {
// or MY_Controller if you use HMVC, linked above
function __construct()
{
parent::__construct();
// Load shared resources here or in autoload.php
}
}
/**
* Back end Controller
*
*/
class Admin_Controller extends MY_Controller {
function __construct()
{
parent::__construct();
// Check login, load back end dependencies
// Create and setup admin user session and other all dynamic admin url for image,js,css,etc..
}
}
/**
* Default Front-end Controller
*
*/
class Front_Controller extends MY_Controller {
function __construct()
{
parent::__construct();
// Load any front-end only dependencies
// Get user data of session and generate other all dynamic front url for image,js,css,etc..
}
}
Back end controllers will extend Admin_Controller, and front end controllers will extend Front_Controller.Now You can create any admin side controller & models and extends to Admin_Controller and front side extends to Front_Controller.
E.g (Any Admin Controller) :
class Admin extends Admin_Controller{
function __construct(){
parent::__construct();
}
}
E.g (Any Front Controller) :
class Home extends Front_Controller{
function __construct(){
parent::__construct();
}
}
Use URI routing where needed, and create separate controllers for your front end and back end side. All helpers, classes, models etc. can be shared if both the front and back end controllers live in the same application.