CodeIgniter 4: Autoload Library

Ryan Dorn picture Ryan Dorn · Nov 17, 2019 · Viewed 14.1k times · Source

I'm using the latest 'master' branch of CodeIgniter 4

I have a Library that I'm trying to load automatically. Effectively, I want to have have 'one' index.php (that has meta, the basic html structure, etc) through which I can load views via my 'Template' Library.

My Library file: (~/app/Libraries/Template.php)

//class Template extends CI_Controller
class Template {

    /* This throws an error, but I will open up a separte thread for this
    public function __construct() {
        parent::__construct();
    }
    */

    public function render($view, $data = array()) {        
        $data['content_view'] = $view;  
        return view('layout/index', $data);     
    }

}

I also have a controller set up:

class Locations extends BaseController
{

    public function index()
    {
        return $this->template->render("locations/index", $view_data); 
        //return view('locations/index');
    }

    //--------------------------------------------------------------------

}

In ~/app/Config/ I added my Library

    $classmap = [
        'Template' => APPPATH .'/Libraries/Template.php'
    ];

I'm getting the following error:

Call to a member function render() on null

What am I doing wrong that's causing my library not to load?

Answer

DFriend picture DFriend · Nov 22, 2019

In CI4 the BaseController is where you create things that you want to be used by multiple other controllers. Creating classes that extend others is so very easy in CI4.

It seems to me that the only thing you are missing is creating the Template class. (There are a couple of other minor things too, but who am I to point fingers?)

One big item that might be just that you don't show it even though you are doing it. That is using namespace and use directives. They are must-do items for CI 4.

Because of where you have put your files you don't need and should remove the following. See how I've used use which imports namespace already known to the autoloader.

$classmap = [
        'Template' => APPPATH .'/Libraries/Template.php'
    ];

First, the BaseController

/app/Controllers/BaseController.php

<?php
namespace App\Controllers;

use CodeIgniter\Controller;
use App\Libraries\Template;

class BaseController extends Controller
{

    /**
     * An array of helpers to be loaded automatically upon
     * class instantiation. These helpers will be available
     * to all other controllers that extend BaseController.
     *
     * @var array
     */
    protected $helpers = [];

    protected $template;

    /**
     * Constructor.
     */
    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        // Do Not Edit This Line
        parent::initController($request, $response, $logger);

        $this->template = new Template();
    }

}

/app/Controllers/Locations.php

class Locations extends BaseController
{
    public function index()
    {
        // set $viewData somehow
        $viewData['someVar'] = "By Magic!";
        return $this->template->render("locations/index", $viewData);
    }
}

/app/Libraries/Template.php

<?php namespace App\Libraries;

class Template
{
    public function render($view, $data = [])
    {
        return view($view, $data);
    }
}

/app/Views/locations/index.php

This works as if... <strong><?= $someVar; ?></strong>

I know I haven't created exactly what you want to do. But the above should get you where you want to go. I hope so anyway.