Ryan Dorn
Ryan Dorn

Reputation: 797

CodeIgniter 4: Autoload Library

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?

Upvotes: 2

Views: 38337

Answers (3)

Dio Lantief Widoyoko
Dio Lantief Widoyoko

Reputation: 161

It's tricky at first. But I managed to run it successfully

Make sure you give it proper namespace

And then just "use" in your controller Location. I dont change anything on Autoload.php.

app/Libraries/Template.php

<?php

namespace App\Libraries;

class Template {
    public static function render($param) {
        return 'Hello '.ucwords($param);
    }
}

The proper way to call is put use App\Libraries\Template just before class Location extends BaseController

app/Controllers/Locations.php

<?php

namespace App\Controllers;
use App\Libraries\Template;

class Locations extends BaseController {
    public function index() {
        $template = new Template();
        $renderedStuff = $template->render('World!');
        echo $renderedStuff;
    }
}

How does this work? Notice in Template.php there is a namespace namespace App\Libraries;, so CI4 will automatically load that library properly also recognize the "Template" class. That is proper way to create CI4 libraries in my point of view.

How do we use that library? Look at my example of Locations.php and then see this code use App\Libraries\Template;, that's how we call that libraries.

How do we call the function? Look inside the index() function, here we call class Template using var $template = new Template();. Then we call render() function in Template library with $template->render('World!');.

Just as simple as that. I hope thats help, lemme know if it doesnt works. :)

Upvotes: 5

DFriend
DFriend

Reputation: 8964

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.

Upvotes: 12

AndiKod
AndiKod

Reputation: 84

Just a little hint, as my eye was hooked by the CI_Controller part.

You seems to use CI3 syntax within CI4, at least about loading the view, which translates to just:

$data = [
    'title' => 'Some title',
];

echo view('news_template', $data);

See the CI3doc vs the CI4doc , the "static page" tutorial.

Upvotes: 0

Related Questions