Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am working with HMVC module extension for codeigniter. Read this wonderful article - Scalable Login System for CodeIgniter – Ion_Auth.
What this article suggests is that we can create multiple custom controllers and based on the logged in user's role, redirect the user to his respective controllers.
For example, for Admin redirect him to a controller that extends Admin_Controller and so on:
class Admin_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
if( ! $this->ion_auth->is_admin()) {
redirect('/');
}
}
}
So, we can apply common rules at the Base controller level itself for all the methods/views within that controller. That is where I have a query: What if i don't want to have global control for all the views within that controller.
Or put in other words - if I need to have specific control for individual views, how to go about it. For example - I have a controller named 'Blog' and methods named - 'view', 'add', 'edit'. Now, view is applicable to all kinds of users, while only Admin should be able to add or edit a blog. Which means I cannot put controller level logic..
class Blog_Controller extends Admin_Controller {
// should be accessible to both Admin and non-logged in user
public function view() {..}
// Following are only accessible to Admin
public function edit() {..}
public function create() {...}
}
One way i can think of is to duplicate code in multiple controllers and handle views specific to the user role.
You could make your Admin_Blog_Controller extend Blog_Controller, load the user data in the User constructor and in the Admin constructor you check for admin access.
That way your admin controller will also contain the method view from the Blog_Controller.
class Admin_Blog_Controller extends Blog_Controller {
public function __construct() {
parent::__construct();
if( ! $this->ion_auth->is_admin()) {
redirect('/');
}
}
public function add() {
}
public function edit() {
}
// Optional, if you want to make custom behaviour
// in the view method of admin:
public function view() {
// Calling parent (Blog_Controller) view method.
parent::view();
// Doing our own stuff.
// ...
}
}
class Blog_Controller extends CI_Controller {
protected $the_user;
public function __construct() {
parent::__construct();
if($this->ion_auth->in_group('user') || $this->ion_auth->is_admin()) {
$this->the_user = $this->ion_auth->user()->row();
$data->the_user = $this->the_user;
$this->load->vars($data);
}
else {
redirect('/');
}
}
public function view() {
}
}
Reading your post again, I realize this was maybe not the exact solution you where asking for, since you want it all in one Controller? I'll not delete my answer regard someone may find it useful still.
Related
I'm not really sure what to do when it comes to dealing with session.
After I log in and set a session data.
How do I keep private pages to only show to those who are logged in.
Do I have to run that kind of validation to all my views?
<?php
if($this->session->userdata('is_loggedin')!=1)
{
redirect('KGindex/index','refresh');
}
?>
I'm not even sure if that is correct, right now it messed up my code. functions don't work anymore.
Where do I run session validations?
You want to be doing this check in your controller rather than in the view. For example
class Account extends CI_Controller {
public function index()
{
if($this->session->userdata('is_loggedin')!=1)
{
redirect('KGindex/index','refresh');
}
}
}
If you know that every function in your controller requires the user to be logged in then you could include the check in the __construct() function as this is called whenever the class is accessed. Therefore you would only need the put the code in one place.
class Account extends CI_Controller {
public function __construct()
{
if($this->session->userdata('is_loggedin')!=1)
{
redirect('KGindex/index','refresh');
}
}
public function index()
{
//__construct() has already been called
}
}
I recently started using Codeigniter after having a structural problem in one of my Ajax-heavy applications. (You can read up on it if you want in my previous question)
I have a fairly short question. Currently I am making a lot of Ajax requests to different controllers. I open the controllers like this:
public function __construct()
{
parent::__construct();
$this->output->set_content_type('application/json');
}
And at the end of every function I do the following:
$this->returnValue['result'] = "ReturnedInfo";
$this->returnValue = json_encode($this->returnValue);
$this->output->set_output($this->returnValue);
The code is pretty clear in itself, but I don't want to keep repeating myself. The codeigniter manual says to do the following:
$this->output
->set_content_type('application/json')
->set_output(json_encode(array('foo' => 'bar')));
But I would still be repeating myself. Also, I don't want to add a function to every controller that does this, even if it does decrease redundancy.
Since all of my controllers return JSON, is there a way to set this globally in a config file maybe, or in any other way?
TL;DR I have this same piece of code in every controller/function. Since the output type is always the same, just not the result, is there a way to automate this process across every controller/function?
Create an Ajax_Controller that extends MY_Controller that extends CI_Controller.
The Ajax Controller will then inherit from both Controllers.
class Ajax_Controller extends MY_Controller
{
public function __construct()
{
parent::__construct();
if(!$this->input->is_ajax_request()) return show_error('Invalid Request');
}
public function jsonOutput($json)
{
//some data checking here....
return $this->output
->set_content_type('application/json')
->set_header("HTTP/1.1 200 OK")
->set_output($json);
}
}
-
class User extends Ajax_Controller
{
public function __construct()
{
parent::__construct();
}
public function userMethod()
{
$json = json_encode(array(
'' => ''
));
$this->jsonOutput($json);
}
}
Extend your controllers from your own base class rather than CI_Controller and put your repeatedly-used function(s) and constructor code in there. Something like:
class BaseController extends CI_Controller {
protected function index() {
$this->returnValue['result'] = "ReturnedInfo";
$this->returnValue = json_encode($this->returnValue);
$this->output->set_output($this->returnValue);
}
}
class Specific extends BaseController {
public function index() {
//do controller-specific stuff
parent::index();
}
}
I abstract this further if I have groups of controllers with shared code; for example, if I had a bunch of controllers that require the user to be logged-in I create AuthenticatedController, which extends BaseController and add session checks etc.
I'm doing a validation in my constructor which checks whether the user has started a session.
I'm then throwing in some controllers for various things.
My question is - can I have some of the controllers unaffected by the construct function(session validation), or do i have to take it into another file? The reason is, that I would like to have two sets of function in the constructor - one for when the user is logged in, and the rest when they are not.
I used to have two files and switch between them, but then i decided to combine them into one.
Thanks
What you need to do is set up a base controller that will look after the session for you and split your logged in controllers from your logged out ones via inheritance.
My suggestion for you is to have a look at Phil Sturgeon's post on Keeping It Dry. In his post, Phil explains the basics on how to implement controllers in such a way that the parent controller will look after sessions so you don't have to check it every time.
As an example:
MY_Controller:
class MY_Controller extends CI_Controller{
function __construct(){
parent::__construct();
//do things in here that ALL controllers should do.
}
}
MY_In_Controller:
class MY_In_Controller extends MY_Controller{
function __construct(){
parent::__construct();
//if user doesnt have the session redirect them out NOW!
}
}
MY_Out_Controller:
class MY_Out_Controller extends MY_Controller{
function __construct(){
parent::__construct();
//if the user has the session, redirect them in NOW.
}
}
Login Controller:
class Login extends MY_Out_Controller{
function __construct(){
parent::__construct();
}
function index(){
//folks that have a session (already logged in) will never even get here.
//because the parent class MY_Out_Controller already redirected them back in.
}
}
Manage Controller:
class Manage extends MY_In_Controller{
function __construct(){
parent::__construct();
}
function index(){
//folks that don't a session (logged out) will never even get here.
//because the parent class MY_In_Controller already redirected them out.
}
}
In short, don't write your session checks directly in controllers. You'll be writing it too often and violating the DRY Principle.
Update: I recommend revamping Phil's method by using Shane Pearson's method in CodeIgniter's Base Classes Revisited.
As stated earlier why don't you use separate different base controllers for specific purpose.
I would suggest as this way for you
let us take two part one let's say frontend controller which donot require session and another controller let's say backend controller which needs session
Now,
//application/core/Front_controller.php
class Front_Controller extends MY_Controller
{
function __construct()
{
parent::__construct();
}
}
another class under core/backend_controller
class backend_Controller extends MY_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('session');
}
}
now you can extend the front_controller for those controller you do not need session and extend backend controller which requires session from application/controller
I need to create codeigniter base controller to check allowed ip address in database by mobel function if the ip is exists then user should go to home page but if the ip address is not exists and show 404 page in codeigniter, i can't find core folder in application folder
First, you need to extend a core class, call it MY_Controller.php
Save that file in: application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->model('ip_table_model');
$this->load->library('input');
// assuming there's a function called "check_ip($ip_address)" in ip_table_model
if (!$this->ip_table_model->check_ip($this->input->ip_address()) {
redirect('error_404');
}
}
}
Now, we're assuming you have a model called ip_table_model which connects to database with list of IP addresses, and there's a function called check_ip which will validate whether user has access or not. This is relatively simple, and I won't show any examples on this.
The redirect('error_404'); page does not yet exist, you need to create a controller which shows your 404 page.
Now, for any other controllers in your project, instead of extends CI_Controller, make them extend MY_Controller instead.
Here's an example:
class Welcome extends MY_Controller {
function __construct()
{
parent::__construct();
}
function index()
{
$this->load->view('welcome_message');
}
}
Explanation: We're extending CI_Controller to create our own core controller, called MY_Controller. Inside, we're checking if user has access or not through the constructor, which will be called in every other controller in the project.
References:
http://codeigniter.com/user_guide/general/core_classes.html
http://codeigniter.com/user_guide/libraries/input.html
Answer is here (section Extending Core Class).
1.7.2 has a different structure to 2.0.*, therefore there is no core folder in application
In Core Create a new Class .
Name MY_Controller.php
class MY_Controller extends CI_Controller {
// Write your functions here which you wanna use throughout the website
public function abc (){
echo "Helllo";
}
}
class Welcome extends MY_Controller {
function __construct()
{
parent::__construct();
}
function your_custom_fuctions()
{
$this->abc(); //echo Hello...
//Anything you want to do
}
}
function admin_view($view_name = "", $header_info = NULL, $sidebar_info=NULL,$page_info = NULL, $footer_info = NULL, $data_info = ""){
$this->load->view('Admin/includes/header', $header_info);
$this->load->view('Admin/includes/Left_sidebar', $sidebar_info);
$this->load->view($view_name, $page_info);
$this->load->view('common/footer', $footer_info);
}
I want to change a specific record in the database using codeigniter. The url should be like this mysite.com/users/edit/10.
Here the user having id=10 is being edited
users is the controller name and edit is a method.
Usually I do in this way
//code of the rest of controller
.....
function edit(){
$uid =$_REQUEST['uid'];
//database update code
}
...
Where a form is being posted deliberately to change the record
You're not clear at all on what you want, I just can give you some pointers.
In CI, you don't need (don't have to) use superglobals to access url parameters. It has a native system to manage uri segments, which became automatically accessible without the need to call them; they're available as arguments of the method you're accessing.
So, in a url like yours, mysite.com/users/edit/10, you'll have
Controller:
class Users extends CI_Controller {
public function edit($uid)
{
// $uid is automatically passed to this method and is already available
// here you do your operations
//for. ex.
$this->load->model('user_model');
$this->user_model->update_user($uid);
}
}
Model:
class User_model extends CI_Model {
function __construct()
{
parent::__construct();
}
function update_user($id)
{
$this->db->where('id',$id);
$fields = array('field1' => 'value1','field2' => 'value2'...);
$this->db->update('users',$fields);
}
}
If you provide further information I could expand my answer.