Reputation: 112
I have a table in MySQL that holds Menu Items, and each has a parent, that can be either 0 (Top Menu) or the ID of another Item.
I'm working on a controller within CodeIgniter that was started by another programmer, and here's the brilliant way he found to sweep through the items of each item, recursively.
// I know there's a better way to do this, but as time is short we have to run
$data['aplicacoes_list'] = '';
$aplicacoes = $this->aplicacoes_model->get_aplicacoes_no_parent();
foreach($aplicacoes as $apl){
$data['aplicacoes_list'] .= '<li class="dd-item" data-id="3">
<div class="dd-handle">'.$apl['nome'].'
<div class="pull-right"><a href="#" id="'.$apl['nome'].'_'.$apl['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$apl['nome'].'_'.$apl['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$apl['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>';
$sub_aplicacoes = $this->aplicacoes_model->get_aplicacoes_by_parent_id($apl['id']);
foreach($sub_aplicacoes as $sub_apl){
$data['aplicacoes_list'] .= '<ol class="dd-list">
<li class="dd-item" data-id="4">
<div class="dd-handle">'.$sub_apl['nome'].'
<div class="pull-right"><a href="#" id="'.$sub_apl['nome'].'_'.$sub_apl['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$sub_apl['nome'].'_'.$sub_apl['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$sub_apl['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>';
$sub_aplicacoes2 = $this->aplicacoes_model->get_aplicacoes_by_parent_id($sub_apl['id']);
foreach($sub_aplicacoes2 as $sub_apl2){
$data['aplicacoes_list'] .= '<ol class="dd-list">
<li class="dd-item" data-id="4">
<div class="dd-handle">'.$sub_apl2['nome'].'
<div class="pull-right"><a href="#" id="'.$sub_apl2['nome'].'_'.$sub_apl2['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$sub_apl2['nome'].'_'.$sub_apl2['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$sub_apl2['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>';
}
}
}
So, as you can see, the list goes on until $sub_aplicacoes7, which is just moronic.
Can you guys think of a better way to accomplish this?
Here's a screenshot of the database, as it is.
Upvotes: 1
Views: 109
Reputation: 2348
Here's a recursive method for you:
private function recursive_aplicacoes( $parent = 0 )
{
$sub_aplicacoes = $this->aplicacoes_model->get_aplicacoes_by_parent_id($parent);
if(!count($sub_aplicacoes)) return '';
$s = '<ol class="dd-list">';
foreach($sub_aplicacoes as $sub_apl)
{
$s .= '<li class="dd-item" data-id="4">
<div class="dd-handle">'.$sub_apl['nome'].'
<div class="pull-right"><a href="#" id="'.$sub_apl['nome'].'_'.$sub_apl['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$sub_apl['nome'].'_'.$sub_apl['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$sub_apl['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>';
$s .= $this->recursive_aplicacoes($sub_apl['id']);
}
$s .= '</ol>';
return $s;
}
Put it in same class.
Here's how to use:
$data['aplicacoes_list'] = $this->recursive_aplicacoes();
Should work :)
Upvotes: 2
Reputation: 3051
You could move the code for generating a submenu into it's own function and use recursion. While this will solve your problem may I recommend that, once you've built the menu for a user that you cache it until s/he logs out as your menu system can quickly become quite complex and slow to load the more embedded menus you add (you end up with an recursive N + 1 problem).
$data['aplicacoes_list'] = '';
$aplicacoes = $this->aplicacoes_model->get_aplicacoes_no_parent();
foreach($aplicacoes as $apl){
$data['aplicacoes_list'] .= '<li class="dd-item" data-id="3">
<div class="dd-handle">'.$apl['nome'].'
<div class="pull-right"><a href="#" id="'.$apl['nome'].'_'.$apl['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$apl['nome'].'_'.$apl['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$apl['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>' . build_submenu($this->aplicacoes_model, $apl['id']);
}
function build_submenu($model, $id) {
$aplicacoes = $model->get_aplicacoes_by_parent_id($id);
if (empty($aplicacoes)) {
return '';
}
$submenu = '';
foreach($aplicacoes as $sub){
$submenu .= '<ol class="dd-list">
<li class="dd-item" data-id="4">
<div class="dd-handle">'.$sub['nome'].'
<div class="pull-right"><a href="#" id="'.$sub['nome'].'_'.$sub['id'].'" data-toggle="modal" data-target="#ModalEditarAplicacao" class="dd-nodrag editarAplicacao btn-xs btn-primary"><i class="fa fa-edit"></i><span class="hidden-block hidden-xs hidden-sm"> Editar</span></a> <a href="#" id="'.$sub['nome'].'_'.$sub['id'].'" data-toggle="modal" data-target="#ModalAdicionarSubaplicacao" class="dd-nodrag adicionarSubAplicacao btn-xs btn-success"><i class="fa fa-plus"></i> <span class="hidden-block hidden-xs hidden-sm">Adicionar subcategoria</span></a> <a href="#" data-toggle="modal" data-target="#ModalRemoverAplicacao" id="'.$sub['id'].'" class="dd-nodrag aplicacaoRemover btn-xs btn-danger"><i class="fa fa-trash-o"></i><span class="hidden-block hidden-xs hidden-sm"> Remover</span></a></div>
</div>
</li>' . build_submenu($model, $sub['id']);
}
return $submenu;
}
You may need to fiddle with this to get the correct HTML tags/CSS that you need.
Upvotes: 0