Welcome Guest, Not a member yet? Register   Sign In
Code Iginter Core subclassing
#1

[eluser]Daniel Peraza[/eluser]
Hi there!.

I am not a guru on PHP but I recently discovered CI and it really surprised me because of its ease of use. Now I'm using CI to develop a simple application for a client which will need session handling and an authentication mechanism, as well as some database operations (as most of the PHP applications nowadays).

They way I'm planning to do this is, first, customizing CI installation in order to separate front-end from back-end applications (which I have already done), and then, using a kind of proxy controller in the back-end, let's say 'Admin', through all the requests will pass. Before redirecting the request to the proper controller, it will check if the current user is logged in, and if not, it will redirect to the proper authentication form. I think this could be implemented in the Admin's constructor, but then I will need a way to make the rest of my constructors inherit from it, which is the problem I face right now. How should be the best way to do this?.

On the other hand, I'm thinking to implement a base class with generic implementations of CRUD queries, storing the DB table name on a member variable, that then all derived classes will customize to perform their tasks with the CI Active Record class. I can't implement this class as a library because CI doesn't allow me to inherit the Model class by this way. Should I use this class as a model?, How should I do this?

I'm just trying to avoid hard-coded require_once constructs, since so far as I have read the documentation available, the CI Loader class always instantiates imported classes which is not necessarily something I want to do.

Please, give me some suggestions on this issue. Thanks in advance.
#2

[eluser]blasto333[/eluser]
What I did is create a base controller that all Admin controllers extend, so that functionality is taken care of.

Secure_Area
Code:
<?php
class Secure_Area extends Controller
{
    /*
    Controllers that are considered secure extend Secure_Area, optionally a $module_id can
    be set to also check if a user can access a particular module in the system.
    */
    function __construct($module_id=null)
    {
        parent::__construct();    
        
        if(!$this->Employee->is_logged_in())
        {
            redirect('login');
        }
        
        if(!$this->Employee->has_permission($module_id,$this->Employee->get_logged_in_employee_info()->person_id))
        {
            redirect('no_access/'.$module_id);
        }
    }
}
?>

Items controller

Code:
<?php
require_once ("Secure_Area.php");
class Items extends Secure_Area
{
    function __construct()
    {
        parent::__construct('items');    
    }
.
.
.    
}
?


I am not sure what you mean on the other question
#3

[eluser]Daniel Peraza[/eluser]
Thank you for answering.

This is the most straight forward way obviously, but I expected to find another way to do it through the Loader class, which is the way that other frameworks use to work, but it seems that CI doesn't work this way.

On the other hand, if you see the basic operations that Active Record class supports, (selection, insertion, editing and deletion) you'll see they work in a very similar way, they just differ in the table they use for their operations, so I'm thinking to write a class like this one:

Code:
<?php
defined('BASEPATH') or die('No se permite el acceso directo a este archivo.');

class DataObject extends Model
{
    protected $_table;
    
    public function __construct($table)
          {
        parent::__construct();
        $this->_table = $table;
          }
    
    public function getAll()
    {
        $query = $this->db->get($this->_table);
        return $query->result_array();
        }
    
    public function get($id)
    {
        $query = $this->db->get_where($this->_table, array('id' => $id));
        return $query->result_array();
    }
    
    public function store($data)
    {
        if(!array_key_exists('id', $data) || empty($data['id']))
        // (Se trata de una insercion:)
        {
            $this->db->insert($this->_table, $data);
        }else{
            // (Efectuaremos una actualizacion:)
            $this->db->where('id', $data['id']);
            $this->db->update($this->_table, $data);
        }
    }
    
    public function remove($ids = array())
    {
           if(!is_array($ids))
                   $ids = array($ids);
          
            foreach($ids as $id)
        {
            $this->db->where('id', $id);
            $this->delete($this->_table);
        }
    }
}
?>

Then all my models will inherit from it. This implementation has the issue that the DataObject model needs to be loaded first in order to be used, thereby, creating an instance of it. I would like to find a way to avoid such instantiation and to import the class without writing hard coded require_once's.
#4

[eluser]Daniel Peraza[/eluser]
Forget it, I found a better answer on http://ellislab.com/codeigniter/user-gui...asses.html, thanks for your help anyway!.
#5

[eluser]reaktivo[/eluser]
[quote author="blasto333" date="1224572853"]What I did is create a base controller that all Admin controllers extend, so that functionality is taken care of.

Secure_Area
Code:
<?php
class Secure_Area extends Controller
{
    /*
    Controllers that are considered secure extend Secure_Area, optionally a $module_id can
    be set to also check if a user can access a particular module in the system.
    */
    function __construct($module_id=null)
    {
        parent::__construct();    
        
        if(!$this->Employee->is_logged_in())
        {
            redirect('login');
        }
        
        if(!$this->Employee->has_permission($module_id,$this->Employee->get_logged_in_employee_info()->person_id))
        {
            redirect('no_access/'.$module_id);
        }
    }
}
?>

Items controller

Code:
<?php
require_once ("Secure_Area.php");
class Items extends Secure_Area
{
    function __construct()
    {
        parent::__construct('items');    
    }
.
.
.    
}
?


I am not sure what you mean on the other question[/quote]


Hello, I was going to open a new thread, but seems I have the same problem, only that I'm subclassing a Model.

Using the code above as example, is there a way to subclass another subclass without using the line
Code:
require_once ("Secure_Area.php");
or loading the first subclass in the autoload? Is this the best way to subclass a subclass?
#6

[eluser]Daniel Peraza[/eluser]
Using http://ellislab.com/codeigniter/user-gui...asses.html, I was able to write a Controller subclass, with the only difference, that in the user guide, the core class is prefixed with CI_, and I had to delete that prefix to get my class working.

But according to the user guide, there is no way to create core Model subclass, because it is not a System Class. So this leaves a great hole in my mind when trying to implement this.

On the other hand, retaking the Controller sub-classing, I have been reading on Design Patterns in PHP, I have no much experience with Design Patterns, but may be using a kind of Access Control - Proxy Design Pattern, we could write a more robust class with all the authentication features centralized in only one class, that then, the rest of the controllers would inherit, checking authentication on every request, and taking the necessary actions when an user is not properly authenticated to access the system.

I tried to implement this using redirections instead of saving member subject objects instances, but I made a mistake and my controller went on recursive redirection instead of calling the proper controller.

I would like to see if somebody else have implemented this idea, or if somebody could outline a basic implementation of this special design pattern. The examples I have found on the web, are all focused in the Remote type of Proxy Design Pattern instead of the Access Control Proxy Design Pattern.
#7

[eluser]Colin Williams[/eluser]
Quote:...checking authentication on every request, and taking the necessary actions when an user is not properly authenticated [sic] to access the system.

Why assume a check must happen for every request? Unless your entire app is on lockdown, you really only need the authorization for specific areas. if (!authorize('action')) redirect('login') is hardly the recipe for all access control scenarios. Please correct me if I've misunderstood your suggestions.
#8

[eluser]Daniel Peraza[/eluser]
Well may be it's just me the one confused, so let me explain better my idea.

My application is a backend application, so I should not grant access to non-administrator users. Hence, I must check on every controller if the user has privileges enough to access to the system before I grant permissions to execute the requested action, right?, so far, this is the classic problem on user authentication. But taking this approach I fear to have to write repeated code on all my controller's constructors, so I prefer to have a single controller with authentication code centralized on it. If all the requests pass through this check, I'd expected the access to be denied to whom (for example) the session time limit expired (please correct me now if I'm wrong on this), or for those users trying to access to a site URI directly without authenticating their selves before.

Am I just misunderstanding the problem or am I right and you get the idea?.
#9

[eluser]Colin Williams[/eluser]
Quote:so far, this is the classic problem on user authentication

It's not a classic problem, it's your app's problem. There are many ways you can make something happen all the time. One way is to use a hook. Another way is to autoload a library and do the authentication/authorization check in its constructor. Yet another way is to have an extra parent controller that the rest of your controllers extend.

And remember, there will be a few pages that you don't want locked out, notably the login page and perhaps a "forgot password" page.

If you really just need to lock down an entire app and don't need role- or group-based permissions, look into using your servers authentication/authorization modules




Theme © iAndrew 2016 - Forum software by © MyBB