2

I'm new in CodeIgniter in general. I have a view layout, on which I have navigation menu bar in it. I want to populate the dropdown menu with categories I've saved in database.

Here's snippet of my layout (View\layouts\frontend.php):

<nav class="navbar navbar-expand-md sticky-top">
    <div class="collapse navbar-collapse flex-column " id="navbar">
        <!-- Brand bar -->
        <a class="navbar-brand ml-3" href="#">
            <span class="">Test Site</span>
        </a>
        <!-- Internal links Menu navbar -->
        <ul class="navbar-nav justify-content-center w-100 px-3">
            <li class="nav-item">
                <a class="nav-link" href="#">Home</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Categories
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                    <a class="dropdown-item" href="#">News</a>
                    <a class="dropdown-item" href="#">Event</a>
                    <a class="dropdown-item" href="#">Announcement</a>
                </div>
            </li>
        </ul>
</nav>

Now, I understand that on every views that Extends that layout, I can just do query on controller and return the view with data. Here's what I've done so far and it works.

Home Controller:

use App\Models\CategoryModel;

class Home extends BaseController
{
    public function index()
    {
        $categoryModel = new CategoryModel();
        $data['categories'] = $categoryModel->orderBy('id', 'ASC')->findAll();
        
        return view('frontend/home_page', $data);
    }
}

Part of layout:

<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Categories
    </a>
    <?php if ($categories) : ?>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <?php foreach ($categories as $category) : ?>
                <a class="dropdown-item" href="#"><?php echo $category['name'] ?></a>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
</li>

But it looks like I have to do that on all controllers' functions that renders my views that use my layout (frontend.php). What I want to ask is, is there a possibility to just make a function/class/something to call so it's only done one time? What is the best practice in this situation?

Codebrekers
  • 754
  • 1
  • 11
  • 29
tuxguitar
  • 21
  • 3

2 Answers2

0

If

$categoryModel = new CategoryModel();
$data['categories'] = $categoryModel->orderBy('id', 'ASC')->findAll();

is something that you plan on calling in multiple methods within that Controller, then yes it would be considered best practice to push that code off into something reusable.

You could ostensibly define this function in several different places, but in this case, a private Controller function is probably easiest (it must be private to prevent it being served by web requests):

private getCategories(){
  $categoryModel = new CategoryModel();
  $ret['categories'] = $categoryModel->orderBy('id', 'ASC')->findAll();
  return $ret;
}

Any other function within that same Controller can then get that data by calling on

$this->getCategories().

parttimeturtle
  • 1,125
  • 7
  • 22
  • Maybe I wasn't being clear enough. What I want is to populate list of categories on my layout template, which is called by all my views. If I apply your method (or the one I am using), I have to reclare getCategories() on all my controllers, correct me if I'm wrong. Is there a way to declare that getCategories() only once and it can be used in all controllers? – tuxguitar Nov 06 '20 at 04:36
  • @tuxguitar You define the function inside the `BaseController` that all of your other Controllers `extend`. – parttimeturtle Nov 06 '20 at 20:51
0

If anyone faces the same problem, here is the way I manage it. Codeigniter has a nice feature view_cell(). You can create a separate class in Libraries folder (let's call it Menu with method display()) and there return a separate view with your menu. Then in your layout call <?= view_cell('\App\Libraries\Menu::display') ?>. This way there is no need to repeat the same code in many controllers.

Ivan Beliakov
  • 529
  • 3
  • 14