Step 3.2 – Administer groups with Ion Auth

Ion Auth library organizes users in groups. In this tutorials we will create a group admin controller. First of all, let’s modify the top menu that can be found inside application/templates/_parts/admin_master_header_view.php so that if the user is an administrator, he/she should see some more links:

<ul class="nav navbar-nav navbar-right">
  <li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><?php print_r($this->ion_auth->user()->row()->username);?> <span class="caret"></span></a>
    <ul class="dropdown-menu" role="menu">
    <?php
    if($this->ion_auth->is_admin())
    {
    ?>
      <li><a href="<?php echo site_url('admin/groups'); ?>">Groups</a></li>
      <li><a href="<?php echo site_url('admin/users'); ?>">Users</a></li>
    <?php
    }
    ?>
      <li><a href="#">Profile page</a></li>
      <li class="divider"></li>
      <li><a href="<?php echo site_url('admin/user/logout');?>">Logout</a></li>
    </ul>
  </li>
</ul>

But wouldn’t that mean that we’ve moved the decisional part of MVC inside the View? You are right. We should compose the the menu in the Admin_Controller (if we go to extreme we should make the menu inside a model…) and only output it inside the View.

So let’s go to our Admin_Controller.php and create a different user menu depending on the group that the user is in:

class Admin_Controller extends MY_Controller
{

  function __construct()
  {
    parent::__construct();
    $this->load->library('ion_auth');
    if (!$this->ion_auth->logged_in())
    {
      //redirect them to the login page
      redirect('admin/user/login', 'refresh');
    }
    $this->data['current_user'] = $this->ion_auth->user()->row();
    $this->data['current_user_menu'] = '';
    if($this->ion_auth->in_group('admin'))
    {
      $this->data['current_user_menu'] = $this->load->view('templates/_parts/user_menu_admin_view.php', NULL, TRUE);
    }
    $this->data['page_title'] = 'CI App - Dashboard';
  }
  protected function render($the_view = NULL, $template = 'admin_master')
  {
    parent::render($the_view, $template);
  }
}

I also passed the current user’s data inside a variable called current_user, so that in the views it will be easier to access that data.

Now, we create the user_menu_admin_view.php inside the application/templates/_parts directory:

<?php defined('BASEPATH') OR exit('No direct script access allowed');?>
<li class="divider"></li>
<li><a href="<?php echo site_url('admin/groups'); ?>">Groups</a></li>
<li><a href="<?php echo site_url('admin/users'); ?>">Users</a></li>

And that’s it.

Now let’s create the Groups page. To do this we will create a new controller file named Groups.php inside application/controllers/admin, and first we make sure that only the admins have access to this controller. If the user is not part of admin group he will be redirected to the dashboard and announced that he/she is not allowed on the groups page:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Groups extends Admin_Controller
{

  function __construct()
  {
    parent::__construct();
    if(!$this->ion_auth->in_group('admin'))
    {
      $this->session->set_flashdata('message','You are not allowed to visit the Groups page');
      redirect('admin','refresh');
    }
  }

  public function index()
  {
  }
}

Let’s put the announcement just after the top menu. We open application/templates/_parts/admin_master_header_view.php and just after the closing </nav> tag we echo the message:

<?php
if($this->session->flashdata('message'))
{
?>
  <div class="container" style="padding-top:40px;">
    <div class="alert alert-info alert-dismissible" role="alert">
      <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
      <?php echo $this->session->flashdata('message');?>
    </div>
  </div>
<?php
}
?>

Now, inside Groups.php let’s just try and return a list with the available groups:

public function index()
{
  $this->data['page_title'] = 'Groups';
  $this->data['groups'] = $this->ion_auth->groups()->result();
  $this->render('admin/groups/list_groups_view');
}

In the view (admin/groups/list_groups_view.php) we create the table:

<?php defined('BASEPATH') OR exit('No direct script access allowed');?>
<div class="container" style="margin-top: 40px;">
  <div class="row">
    <div class="col-lg-12">
      <a href="<?php echo site_url('admin/groups/create');?>" class="btn btn-primary">Create group</a>
    </div>
  </div>
  <div class="row">
  <div class="col-lg-12" style="margin-top: 10px;">
    <?php
    if(!empty($groups))
    {
      echo '<table class="table table-hover table-bordered table-condensed">';
      foreach($groups as $group)
      {
        echo '<tr>';
        echo '<td>'.$group->name.'</td><td>'.$group->description.'</td><td>'.anchor('admin/groups/edit/'.$group->id,'<span class="glyphicon glyphicon-pencil"></span>');
        if(!in_array($group->name, array('admin','members'))) echo ' '.anchor('admin/groups/delete/'.$group->id,'<span class="glyphicon glyphicon-remove"></span>');
        echo '</td>';
        echo '</tr>';
      }
      echo '</table>';
    }
  ?>
  </div>
</div>
</div>

“admin” and “members”, being the default groups, should not have a delete link. So, let’s remove it:

Now, let’s return to our Groups controller, by making three new methods: create(), edit() and delete().

The groups/create page

The create() method:

public function create()
{
  $this->data['page_title'] = 'Create group';
  $this->load->library('form_validation');
  $this->form_validation->set_rules('group_name','Group name','trim|required|is_unique[groups.name]');
  $this->form_validation->set_rules('group_description','Group description','trim|required');

  if($this->form_validation->run()===FALSE)
  {
    $this->load->helper('form');
    $this->render('admin/groups/create_group_view');
  }
  else
  {
    $group_name = $this->input->post('group_name');
    $group_description = $this->input->post('group_description');
    $this->ion_auth->create_group($group_name, $group_description);
    $this->session->set_flashdata('message',$this->ion_auth->messages());
    redirect('admin/groups','refresh');
  }
}

The create_group_view view:

<?php defined('BASEPATH') OR exit('No direct script access allowed');?>
<div class="container" style="margin-top: 40px;">
  <div class="row">
    <div class="col-lg-4 col-lg-offset-4">
      <h1>Create group</h1>
      <?php echo $this->session->flashdata('message');?>
      <?php echo form_open('',array('class'=>'form-horizontal'));?>
        <div class="form-group">
          <?php echo form_label('Group name','group_name');?>
          <?php echo form_error('group_name');?>
          <?php echo form_input('group_name','','class="form-control"');?>
        </div>
        <div class="form-group">
          <?php echo form_label('Group description','group_description');?>
          <?php echo form_error('group_description');?>
          <?php echo form_input('group_description','','class="form-control"');?>
        </div>
        <?php echo form_submit('submit', 'Create group', 'class="btn btn-primary btn-lg btn-block"');?>
      <?php echo form_close();?>
    </div>
  </div>
</div>

The groups/edit page

The edit() method:

public function edit($group_id = NULL)
{
  $group_id = $this->input->post('group_id') ? $this->input->post('group_id') : $group_id;
  $this->data['page_title'] = 'Edit group';
  $this->load->library('form_validation');
       
  $this->form_validation->set_rules('group_name','Group name','trim|required');
  $this->form_validation->set_rules('group_description','Group description','trim|required');
  $this->form_validation->set_rules('group_id','Group id','trim|integer|required');

  if($this->form_validation->run() === FALSE)
  {
    if($group = $this->ion_auth->group((int) $group_id)->row())
    {
      $this->data['group'] = $group;
    }
    else
    {
      $this->session->set_flashdata('message', 'The group doesn\'t exist.');
      redirect('admin/groups', 'refresh');
    }
    $this->load->helper('form');
    $this->render('admin/groups/edit_group_view');
  }
  else
  {
    $group_name = $this->input->post('group_name');
    $group_description = $this->input->post('group_description');
    $group_id = $this->input->post('group_id');
    $this->ion_auth->update_group($group_id, $group_name, $group_description);
    $this->session->set_flashdata('message',$this->ion_auth->messages());
    redirect('admin/groups','refresh');
  }
}

Maybe this one needs a little explanation: if the run() method of the form_validation library returns true, then everything is a go. Else if we get the group data from the ion_auth library by passing the id of the group from the URL, we setup the form with the group data. Else, there is no group data, and that id doesn’t exist, so we redirect.

The edit_group_view view:

<?php defined('BASEPATH') OR exit('No direct script access allowed');?>
<div class="container" style="margin-top: 40px;">
  <div class="row">
    <div class="col-lg-4 col-lg-offset-4">
      <h1>Edit group</h1>
      <?php echo form_open('',array('class'=>'form-horizontal'));?>
        <div class="form-group">
          <?php echo form_label('Group name','group_name');?>
          <?php echo form_error('group_name');?>
          <?php echo form_input('group_name',set_value('group_name',$group->name),'class="form-control"');?>
        </div>
        <div class="form-group">
          <?php echo form_label('Group description','group_description');?>
          <?php echo form_error('group_description');?>
          <?php echo form_input('group_description',set_value('group_description',$group->description),'class="form-control"');?>
        </div>
        <?php echo form_hidden('group_id',set_value('group_id',$group->id));?>
        <?php echo form_submit('submit', 'Edit group', 'class="btn btn-primary btn-lg btn-block"');?>
      <?php echo form_close();?>
    </div>
  </div>
</div>

The groups/delete “page”

Well… this one is not really a page… it’s only a method that will redirect to the groups page after it does its job:

public function delete($group_id = NULL)
{
  if(is_null($group_id))
  {
    $this->session->set_flashdata('message','There\'s no group to delete');
  }
  else
  {
    $this->ion_auth->delete_group($group_id);
    $this->session->set_flashdata('message',$this->ion_auth->messages());
  }
  redirect('admin/groups','refresh');
}

And that’s it… Next we will see how we can administer the users using Ion Auth library.

21 comments

  1. Is there anywhere to see the finished work? To catch any errors. I was having problem with session. Also, I’m getting menus listed on the left side of the page. Somewhere I got the impressions the menu was horizontal at the top of the page.

  2. It all almost works for me thank you..
    I still have a problem, when I go to ‘admin/groups/create’ page
    and try to click the administrator menu, it won’t show the dropdown list.. why..?

  3. Great tutorial..as usual. I’m following all your tutorial to build my new project, Learning CI and OOP. Keep up the great work.
    Just a litte note (sorry for that..hope you don’t mind and maybe I’m wrong): in the create() method I’ve had to remove the following code at row 21:
    $this->render(‘admin/groups/create_group_view’);
    or my body page is printed twice on browser
    Thanks

  4. Hi, in the code of the groups/delete “page” the function called for deleting a group is “delete_group” instead of “delte_group” (mistake in code example row no. 9 😉
    Great tutorial !!! =)

  5. Hello,
    Just a note:
    we can’t delete groups whose name is ‘admin’ or ‘ members’.
    But…. if we rename them: we can now do it !
    So I see two possible solutions:
    1) does not allow to edit the name of these groups
    or
    2 ) allow rename them, but do not let delete groups with id 1 and 2.
    It’s not ideal, but it is a additional precaution, isn’t it?

    1. Indeed. You are very right. “admin” and “members” groups are mentioned inside the configuration file, which means that any change on their name will affect the library unless you do the same changes to the configuration file. Thank you for pointing that out.

  6. Loving your tuts, they are the best I have come across so far and I’ll definitely buy you a coffee once I’ve finished. As I’m fairly new to php and CI, can you explain two things for me though in the edit() method?
    1. NetBeans IDE is giving me a message on line 3 about dual assignments?
    2. also on line 13 NetBeans is saying, accidental assignment in a condition, I’m assuming it has to do with ((int) $group_id).
    Everything works so far with the tuts, I would just like some clarification on what the two lines mean.

    Thanks
    Tony

    1. I am not using NetBeans…
      1. I do not know what dual assignments mean; I do not know what the third line is 🙂
      2. What you assume is somewhat wrong. That is in fact named “typecasting” of a variable (we are making sure that we are sending an integer).
      “Accidental assignment in a condition”? Is not accidental 🙂 At least in PHP, if inside an “if” statement we put an assignment, the “if” will either receive a true or a false depending on the assignment. What I mean by this is that if “$this->ion_auth->group((int) $group_id)->row()” would have returned FALSE (the model returns false if there is no group with that ID), the “if” condition would have not been ran.

      You’re welcome. And thank you for the coffee in advance 🙂

      1. Thanks for the quick response. Cool so I understand the typecasting, the third line reads:
        $group_id = $this->input->post(‘group_id’) ? $this->input->post(‘group_id’) : $group_id;
        I’m unsure of what this means.

        Thanks again

        Tony

        1. That is a ternary operator. It’s some sort of shorter version of an if-else statement. it translates to (is it true that…) ? (do this if true) : (do this if false);

          In that particular line I am asking “is it true that there exists a post data value for “group_id”?”. If it’s true, return the post data, else use the $group_id variable. After the check was done, and a value was returned, that value is assigned to $group_id. You may find this line to to be superfluous, as there is no sane person that will change the url when using a form, but… who knows?… Is better not to trust the users’ sanity 😉

  7. Hi,

    First of all, thanks. Your tutorials are the best, they help me a lot lerning codeigniter.
    I use a few cases in a project i have in hands. Now i like to ask something, if possible, you could explain how to use HMVC with the templates structure you have implemented here?

    Many thanks.

    Kind regards,
    Liberal

  8. Hi, thanks for the great tut, really appreciated!

    in this section i found 3 typos – maybe you want to amend it:

    1) you make changes to Admin_Controller.php – it should be MY_Controller.php
    2) a few lines below that the path to views is missing the “views” part 🙂
    3) moving the decisional code from admin_master_header_view.php into MY_Controller.php could maybe improved as in this case the master controller actually builds the menue…i would use a dedicated piece of code for that. either way – there is a mistake as you don’t amend the admin_master_header_view.php after moving the code – it should at lease include

    Hoping for many more of your great tuts!
    /tede

  9. Hello,Great tutorial,
    But I can edit my groups,it is returning with the message ‘The group doesn’t exist.’
    why?

Leave a Reply

Your email address will not be published.

No spam? * Time limit is exhausted. Please reload CAPTCHA.