Welcome Guest, Not a member yet? Register   Sign In
Autoload for models like BaseController
#1

So I'm working on CodeIgniter 4 lately and I'm trying to put my code from my CodeIgniter 3 project to CodeIgniter 4. Which isn't very easy. I want to use CodeIgniter 4 the best way possible, which is why I'm wondering, what is the best way to include certain functions for all of my models and views.

Autoload for models is gone, I'm aware of that. Instead there is the BaseController. My initController in the BaseController looks like this:

PHP Code:
public function initController(RequestInterface $requestResponseInterface $responseLoggerInterface $logger)
    {
        
// Do Not Edit This Line
        
parent::initController($request$response$logger);

        
//--------------------------------------------------------------------
        // Preload any models, libraries, etc, here.
        //--------------------------------------------------------------------
        // E.g.: $this->session = \Config\Services::session();
        
$this->session = \Config\Services::session();
        
$this->db = \Config\Database::connect();

        
$this->uri = new \CodeIgniter\HTTP\URI(current_url(true));
        
        
$this->settings = new settings_model();
        
$this->search = new search_model();
        
$this->pages = new pages_model();
    } 

I can use everything in the BaseControntroller inside my other controllers, which is great. However, is there a way to do the same for the models and for the views or do I have to include all the function inside each model and view?

I can put some functions inside the '__construct' of my model, but it's still not very convenient. Things like a database connection and uri use are so commonly used that it feels like a hassle to include them every time. It feels like a step back then a step forward.
Reply
#2

You can create a base model and extend your other model on it.

You don’t need to deal with database connection. Your model connects automatically to the database and the db object is already available. 
Example: $myModel->db->affectedRows().

You can also autoload helpers in your controller: http://codeigniter.com/user_guide/incomi...ml#helpers
Example: protected $helpers = ['url', 'form'];
CodeIgniter 4 tutorials (EN/FR) - https://includebeer.com
/*** NO support in private message - Use the forum! ***/
Reply
#3

(06-19-2021, 09:40 AM)includebeer Wrote: You can create a base model and extend your other model on it.

Thanks for you reply. I didn't know that you can make a base model. What is the content of the base model then? I now have this:

PHP Code:
namespace App\Models;
use 
CodeIgniter\Model;
class 
BaseModel extends Model {

 public function 
initModel(RequestInterface $requestResponseInterface $responseLoggerInterface $logger) {

 
$this->session = \Config\Services::session();
 
 
$this->uri = new \CodeIgniter\HTTP\URI(current_url(true));
 }
}
?>

And I added it to a normal model like this:

PHP Code:
class User_accounts_model extends \App\Models\BaseModel 

I realize that the name of the function might not work. But what must be the name of that?

(06-19-2021, 09:40 AM)includebeer Wrote: You don’t need to deal with database connection. Your model connects automatically to the database and the db object is already available. 
Example: $myModel->db->affectedRows().

Sounds handy. But where do you declare $myModel in your example? I used it like this:

PHP Code:
    function get_user_accounts(){
            $builder $this->db->table('user_accounts ua');
 
    $builder->select('ua.user_account_id');
 
    $builder->where('ua.offline'0);
 
    $query $builder->get();
 
    $result = (array)$query->getResult('array');
 
    return $result;
    

Which seems to work, but I had to declare $this->db in the __construct first to make it work. I only hate that the from is above the select.
Reply
#4

Unlike CI3, version 4 has convenient ways for accessing components on-the-fly. There is nothing wrong with preloading instances into your BaseController but a) you run the risk offloading things you never use for a performance hit, and b) these instances would need to be passed from your Controller if you want them accessible anywhere else.

For starters I recommend reading up on Services. This is CI4’s version of a dependency container - a way of making “shared instances” of various components available to other components. So I’m your example, instead of preloading a URI instance you can just grab it when you need it:

service('uri')->setPath('foo/bar');


Because Services is managing your instances, this will be the same object anywhere you call it. So if the above code was in a Filter then you can reuse the same URI in your view:

Current path is <?= service('uri')->getPath() ?>
Reply
Reply
#6

As for the BaseModel.php. Find it out later.

The BaseModel should look like this:

PHP Code:
namespace App\Models;
use 
CodeIgniter\Model;
class 
BaseModel extends Model {

    function 
__construct(){
        
$this->session = \Config\Services::session();
        
        
$this->uri = new \CodeIgniter\HTTP\URI(current_url(true));
    }


And it should be looking like this in your model:
PHP Code:
class User_accounts_model extends \App\Models\BaseModel {

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


At least, this seems to work.

(06-22-2021, 05:22 AM)MGatner Wrote: Unlike CI3, version 4 has convenient ways for accessing components on-the-fly. There is nothing wrong with preloading instances into your BaseController but a) you run the risk offloading things you never use for a performance hit, and b) these instances would need to be passed from your Controller if you want them accessible anywhere else.

For starters I recommend reading up on Services. This is CI4’s version of a dependency container - a way of making “shared instances” of various components available to other components. So I’m your example, instead of preloading a URI instance you can just grab it when you need it:

service('uri')->setPath('foo/bar');


Because Services is managing your instances, this will be the same object anywhere you call it. So if the above code was in a Filter then you can reuse the same URI in your view:

Current path is <?= service('uri')->getPath() ?>
Thanks for your response and advice. That seems to be what I'm looking for. I will read into that.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB