3
\$\begingroup\$

I'm newly working with CodeIgniter and PHP. I wrote a category structured 'pages' code with listing pages as multilevel list or indented select box.

page                                        page_lang
-------------------------------------       ----------------------------
id_page | id_menu | id_parent | level       id_page |  title     | etc..
-------------------------------------       ----------------------------
   1    |    1    |     0     |   0            1    | Name 1     | etc..
   2    |    1    |     1     |   1            2    | Name 1.1   | etc..
   3    |    1    |     2     |   2            3    | Name 1.1.1 | etc..
   4    |    1    |     2     |   1            4    | Name 1.2   | etc.

My controller:

function get_menu_content($id_menu, $id_parent = 0, $level = 0)
{
  echo '<select>';
  $dropdown = $this->my_model->get_menu($id_menu,'dropdown');
  echo $dropdown;
  echo '</select>';  //echo in controller for quick test purpose
}

My_model has three functions: the first is getting result array, the other two is rendering as list and options.

class My_model extends CI_Model
{

  public $model_result;

  function __construct()
  {
     parent::__construct();
  }

function get_menu($id_menu = '1',$type = 'list')
{
  $sql = "
  SELECT a.id_parent, b.id_page, a.level, b.title 
  FROM page a
  INNER JOIN page_lang b ON a.id_page = b.id_page 
  WHERE 
    a.id_menu = $id_menu";  
  $query = $this->db->query($sql);  

  if($query->num_rows() > 0)
  {
    $res = $query->result_array();
    foreach($res as $row):
      $items[$row['id_parent']][] = $row;
    endforeach;
    if($type =='list') $this->_menu_list($items); //renders ul tags
    if($type =='dropdown') $this->_menu_dropdown($items); //renders option tag
    return $this->model_result;
  }
}

function _menu_list($items, $parent = null)
{
  $index = $parent == null ? '0' : $parent;  
  if (isset($items[$index]))
  {
    $this->model_result .= '<ul';
    $this->model_result .= $parent == null ? ' id="category" ' : '';
    $this->model_result .= '>';    
    foreach ($items[$index] as $child)
    {
      $this->model_result .= '<li rel="'.$child['id_page'].'">'.$child['title'];
      $this->_menu_list($items, $child['id_page']);
      $this->model_result .= '</li>';
    }    
    $this->model_result .= '</ul>';
  }
}

function _menu_dropdown($items, $parent = null, $level = '0')
{
  $index = $parent == null ? '0' : $parent;
  $space = str_repeat(' &nbsp &nbsp ', $level);
  if (isset($items[$index]))
  { 
    foreach ($items[$index] as $child)
    { 
      $this->model_result .= '<option value="'.$child['id_page'].'">'.$space.$child['title'].'</option>' . "\n";
      $this->_menu_dropdown($items, $child['id_page'],$level+1);
    }
  }
}

It works a bit slowly. I need a cleaner code I guess. I will appreciate any improvement on the code based on my database structure.

\$\endgroup\$
1
\$\begingroup\$

How slow is it? Did you measure it? Do you have a lot of nodes? A performant way to store hierarchies in databases is the nested set model.

Also, why are you doing rendering in the model? Did you read CodeIgniter tutorials explaining how Model/View/Controller works?

\$\endgroup\$
  • \$\begingroup\$ Nested set model is quite difficult for me to handle it successfully. Especially when order changes. Model is not the right place, I know. but it clearly keeps controller clean to focus main things. Is there any other way to keep this kind of functions outside controller or model? \$\endgroup\$ – yahyaE Mar 7 '12 at 17:46
  • \$\begingroup\$ Yes, use a View. How many nodes do you have in your tree? If less than a hundred, I don't think the nested set model will bring huge improvements. \$\endgroup\$ – Quentin Pradet Mar 7 '12 at 19:07
2
\$\begingroup\$

One general comment -> YOU ARE NOT ESCAPING $id_menu IN YOUR SQL QUERY!

There is a section on how to do this in the CodeIgniter Database Query Documentation.

I'm not familiar with Code Igniter but there is nothing obvious that jumps out at me as to why this would be slow.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.