Member Avatar for iamthwee

Hey guys,

At the moment I have an if == admin then show admin form on my views.

I guess it was more for the sake of convenience rather than anything else. Is it best practice to create a separate controller and view for an admin panel and place this in a separate directory?

ta.

Member Avatar for iamthwee

bump

I would difinitely create a separate controller and methods intended for the admin. For example, if we have a url mydomain.com/admin/settings/, then our object will be called admin and the method is called settings.

Using the target url above we can device our admin class

class Admin extends CI_Controller {

    public function __construct(){
            $this->load->helper('url');
            $this->load->library('session');
            ## we can also load the form validation and form helper here if needed.
            }

    public function settings(){

        ## if logged_in and privs is equal to admin
        ## set is_admin to session

        }

   /*
   * create methods for whatever options available to the admin
   */

   public function manage_users(){

   ##create Admin_model class with method called get_users()
   ## we can load our database and then create an instance of the Admin_model

   $this->load->database();
    $this->load->model('admin_model');

    ## send members array to the view
    $these_members = $this->admin_modle->get_users();

    }

    }

so if the user is admin and the session is_admin exists, then mydomain.com/admin/settings and mydomain.com/admin/manage_users can be served.

just to add a little more on the admin class. we can also create separate methods for the user management interface. In my example, above I created method called manage_users() which is intended to all registered users.

Another question that may come up will be how to execute the actions by the admin ? e.g. delete user, add user, suspend user, etc..

A good approach in implementing this can either creating separate method or can be included in the manage_users method. I prefer the first, because it will be a lot easier to submit form.

suppose we have a form to manage members

<form action="mydomain.com/admin/delete_user/" method="post">
<input type="hidden" value="member_id"/>
<input type="text" name="delete_m" value="member username from database"/>
</form>

The form is normally attached by the codeigniter to the view. Something like this.. this is just an example form attributes assignment in CI.

$attributes = array('class' => 'manage_users', 'id' => 'm_users');

## we can send the form to the template file
$form_array =  array(
                'form'=> form_open('admin/delete_user',$attributes),
                'form_submit'=>form_submit( 'submit', 'Delete')
                );

Our template file can be something like this

 <?php echo $form_array['form'];?>
 <input type="text" name="delete_m" value="member username from database">
 <!-- we call the form submit -->

 <?php echo $form_array['form_submit'];?>
 <!-- lastly, we close the form -->

 </form>

If we run the codes above the form will be posted to /admin/delete_user. Again, this is a classic CI convention in practice here. The router will look for the admin object and for the delete_user method.

We can add the delete_user method like so;

public function delete_user($memberId){
    ## call the model method for deletion here e.g.
    $this->admin_model->delete_user($memberId);

    ## send to the template file
    $deleted_response = 'user deleted';

    }

The same exact format and patterns applies to adding, modifying, updating the members information.

we can also assign the default page for the admin if session and log-in are validated. We can do this by creating the default function index or method index().

public function index(){

    ## validate admin credentials
    ## show whatever contents the admin needs to see after log-in validation

    ## send output to the template file

    ## if the session expired, the log-in credentials are no longer valid, send the user to the login page.

    if( not admin or not logged in or the session logged_in does not exists){
    //redirect('login/','location');

    }

    }

CI is using two different redirects refresh and location ( this is the second parameters of the function redirect. I strongly recommend location as the second parameter because it is somewhat faster).

Member Avatar for iamthwee

Thanks for the thorough explanation. I will need a little time to digest that and plan it through.

Slightly offtopic here but you seem very comfortable with CI. Can you take a look at my ultralite forum I've written.

http://www.daniweb.com/web-development/php/threads/475235/forum

Half way through I have attached a zip file called forums-7.zip

If you could critique the current code, give me an idea if I'm following the MVC pattern properly or if you notice any bugs I would be SOOOO grateful!

Thanks.

okay, I will download it and take a look at the source code.

I have a minor corrections on my recommendations above. I mentioned that CI uri convention was mydomain.com/controllers_name/method_name/. However, the out of the box CI was not like that. It is like this mydomain.com/index.php/controllers_name/method_name/.

To eliminate the index.php in the middle of the url, we need to add this .htaccess file in the installation directory

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]  

That should eliminate the needs of typing index.php .

When I was learning about MVC design patterns, my older brother told be to practice on CI. Although I am Zend Certified, my very first taste of PHP MVC framework was in CI and not in Zend Framework.

I also wrote a PDO CRUD library for CI, because the database library is getting really old now.

commented: super! +14

I am currently looking at your ultralite forum application. I have few recommendations later on. For now, I would like to recommend adding adding a constructor on the the application's controllers. Just make sure prior to releasing the application, remove all the echo from the controller file.

For example, on the file called /application/controllers/forum.php, it would be nice to add a constructor. Kind'a like this

class Forum extends CI_Controller {

public function __construct(){

    parent::__construct();

        ## this is also the perfect time to load helpers and library
        ## if the application will be using non-persistent database connection, then this is the right place to set an instance of the database for the model to use.
        $this->load->database();
        $this->load->model('Stuff');
        $this->load->helper("url");
        $this->load->library("pagination");// paginating long results



}

public function index()
{
    // main index function  
}

## rest of the forums methods here



}

Some people reading this maybe wondering why did veedeoo load the database on the controller's contructor? Isn't it suppose to load in the application's model class? The questions are pretty valid and yes we are supposed to load database on the model class. In fact, the CI documentation suggested to set the database connection in the model class. However, if we want to run 4 different models in one controller, we want the database connection to be persistent in that very specific controller, instead of renewing an ovelapping database connection throughout the application. Unless, there is a sigleton library that we can use to confirm if the database connection class instance already exists somewhere in the background.

Side Note: When I said database connection persistent above, the main configuration file should be set to persistent connection equal to FALSE. This will prevent all unecessary database connections running in the background without purpose.

Below is a classic example of less server resource application with single controller rendering 4 different models and 4 different views. This is one of the many reasons why people should fell in love with CI. The extensibility and ability to develop an application in few controller files is pretty much possible. Unlike in other frameworks, where mandatory M V C patterns are strictly enforced.

Let say,we have one controller called forum. We want this controller to render 4 different requests and deliver them into 4 different template files and of course 4 different models in the background. The most logical url's are domain.com/forum/latest, /forum/most_viewed/, /forum/most_commented/, /forum/most_popular/.

This is just an example... it is pretty clear that we can even use a single model class for the above, but someday somehow we will encounter a situation where 4 separate models has to be written. e.g. complete separation of concern as it applies to the Model and Views or Isolation of transactions between models and between views. e.g isolation of session variables to specific model class only, isolation of admin privs in a single user database.

class Forum extends CI_Controller {

public function __construct(){

    parent::__construct();

        ## this is also the perfect time to load helpers and library
        ## if the application will be using non-persistent database connection, then this is the right place to set an instance of the database for the model to use.
        $this->load->database();
        $this->load->model('Stuff');// this the basic model for the content without control
        $this->load->model('most_viewed'); //second model for most viewed
        $this->load->model('most_popular');//third model
        $this->load->model('most_commented');//fourth model
        $this->load->helper("url");
        $this->load->library("pagination");// paginating long results



}

public function index()
{
    // main index function  
}

## rest of the forums methods here

## second method for redering second model

public function most_viewed(){

$most_v = $this->most_viewed->get_post();

## assign the output from the most_viewed model to the template file
$this->load->view('forum/mostviewed', $most_v);


}

## do the remaining of the models and assigning its returned content array to separate template file.


}

If properly coded, the simple controller above can deliver contents based on these uri requests.

/forum/most_viewed/
/forum/most_popular/
/forum/most_commented/
/form/latest/
/form/

We can simply route them like this

$route['most_viewed/:num'] = 'most_viewed';// the rest are just identical to this. /: num will only be triggered when we are expecting a paginated result, but in practice it is always good to anticipate for a broader requests.

The above is a classic example of flexibility of the CI routing mechanism . It is so flexible that we can probably get away without even including it on the routes.php, but there are some exceptions to this. It all depends on the situations at hand.

Another efficient alternative is to load these models

 $this->load->model('Stuff');// this the basic model for the content without control
$this->load->model('most_viewed'); //second model for most viewed
$this->load->model('most_popular');//third model
$this->load->model('most_commented');//fourth model

to the controller's method needing them. The reason is that the model will not be instantiated until the browser request the most_viewed method.

public function most_viewed(){

    $this->load->model('most_viewed');
    $this->load->view('forum/mostviewed', $this->most_viewed->get_post());

    }

That should deliver the most_viewed content from the most_viewed model class==> method get_post() to the template file mostviewed.php

By doing this alternative, we isolated the instantiation of the model objects only when needed, instead of loading them in the instantiation of the object forum.

Member Avatar for iamthwee

Thanks veedeo, I need to read that then I will ask more questions.

For the time being can you post any of my superlite forum replies in the forum thread I created otherwise it will get confusing.

I want them all kept together. I made a few major update releases so there is a new codebase to examine.

ta.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.