setModel missing explanation

I’ve been trying for a couple days to create a custom model. The documentation for CodeIgniter 4 is completely missing.

I used to be able to use $this->db in codeigniter 3 while using GC but I can’t do that in CI4 so what is the equivalent?

Hello @gabe152006 and welcome to our forums :hugs: ,

For Codeigniter 4 you should use Codeigniter Models and call them in your function. $this->db was removed from Codeigniter 4 as it was an anti-pattern to be able to use the database from everywhere. Now you can use directly $db only from the Model it self as it is extending Model.

So for example instead of having:

public function getOne($id)
    {
        $customer = parent::getOne($id);

        $this->db->select('COUNT(*) as count_orders');
        $this->db->where('customerNumber', $id);
        $customer['count_orders'] = $this->db->get('orders')->row()->count_orders;

        return $customer;
    }

You will have something like this:

public function getOne($id)
    {
        $customer = parent::getOne($id);

       $customerModel = new \App\Models\CustomerModel();
        $customer['count_orders'] = $customerModel->getCountOders($id);

        return $customer;
    }

As Codeigniter 4 documentation is not that clear, I would like at the future to also create a video turorial for Codeigniter 4 models as part of my youtube tutorial series Codeigniter 4 Tutorial - YouTube , but for now I can copy-paste an example of a Model I am using for the blog of the website :slight_smile:

<?php namespace App\Models;

use CodeIgniter\Model;

class BlogModel extends Model
{
    public function getBlogPosts() {
        $blogPosts = $this->db->table('nw_blog_posts')->orderBy('insert_datetime', 'desc')->get()->getResult();

        foreach ($blogPosts as $num_row => $blogPost) {
            $blogPosts[$num_row]->insert_datetime_pretty = date_format(date_create($blogPost->insert_datetime), 'M d,Y');
        }

        return $blogPosts;
    }
}

Hi @johnny !

Thank you so much for providing this explanation.

I am a little confused in terms of how the GroceryCrud Enterprise Models work.

In CI4 I’m able to create my own models and call them out in my controllers and that’s it. In GC, do I need to use the specific functions listed in Model.php in \GroceryCrud\Core\Model and call the CI4 models within these functions?

I know GC uses Zend which is why I’m a bit confused here. Basically I’m trying to SUM all the values of a few columns while I group by some columns which I can do in CI4 just fine but how do I call this query into GC?

I have my custom CI4 Model that returns exactly what I want:

<?php
namespace App\Models;

use CodeIgniter\Model;

class ProjectionsModel extends Model 
{
	
	public function getSum() {
		$builder = $this->db->table('projections')
		->selectSum('sum_total', 'our_sum')
		->selectSum('sum_cleared', 'our_cleared')
		->selectSum('sum_planned_spend', 'our_planned')
		->selectSum('sum_projected', 'our_projected')
		->groupBy('quarter_id')
		->groupBy('year_id');
		$query = $builder->get()->getResult();
		
		return $query;
		
	}
	
}

how do I use this model using the setModel() function of GroceryCrud Enterprise?

With Codeigniter 3 and GC V1.x I was able to filter my query before calling GroceryCrud without a model and it would work like:

$crud = new grocery_CRUD();
$crud->set_table('test');
$this->db
->select('sum(cost) as our_sum')
->group_by('type')
->order_by('our_sum', 'desc');
$output = $crud->render();
$this->load->view('WriteHereYourView.php', $output);

Now I can’t find how I can do something similar with or without a model.

Thank you so much

@johnny any insight?

Hello @gabe152006 these are lot of questions in 1 post I have to say.

Question 1. Is documentation for custom model outdated?

Let’s start with the simple fact that you are right. It is not that simple to understand how to use the custom Model as the documentation is pretty small: setModel | Grocery CRUD .

I will keep a note to update the documentation with an example of some zend db queries that people can add so we can also have a framework agnostic example. The funny story is that the day that I would do that Grocery CRUD will get an update to lamina project so the documentation will be once again outdated. This is what happened with the CI 3 example to be honest, I had the example few months before the release of CI 4 went live. Anyway… that’s a story for another day :grinning:

The important thing for now is to keep the main idea of custom models for Grocery CRUD Enterprise.

Question 2. How to use CI4 Models into Grocery CRUD Models?

This is as simple as using the model into. Please do not underestimate step 1 and step 2 as these are important to make sure that you have the Model loaded correctly.
Step 1. Create an empty custom model by simply just extending the Model. For example:

<?php

use GroceryCrud\Core\Model;

class customModel extends Model {
    
}

Step 2. Load your CI4 Model with use and just make sure that there is not any error:

<?php

use GroceryCrud\Core\Model;
use App\Models\BlogModel; // <---

class customModel extends Model {

}

Step 3. Now open the Grocery CRUD Enterprise Model that we are extending (if you are using a smart IDE you can do that by simply pressing Ctrl/Cmd + Click) and start replacing the functions that you wish. For example let’s say that we would like to replace the most common function that is our grid queries, for those we use the functions getList and getTotalItems (for the paging)
As far as getTotalItems returns a number and getList is returning an array of fields, you can add pretty much everything you wish. For example:

    public function getList()
    {
        return [
            [
                'id' => '3',
                'name' => 'Dummy Data 1',
                'a_relation' => '36'
            ],
            [
                'id' => '2',
                'name' => 'Dummy Data 2',
                'a_relation' => '6'
            ]
        ];
    }

    public function getTotalItems()
    {
        return 2;
    }

Now in your case your custom model will look like this:

<?php

use GroceryCrud\Core\Model;
use App\Models\ProjectionsModel;

class customModel extends Model {
    public function getList()
    {
        // For CI4 you should use $query->getResult('array') instead of $query->getResult()
        // that we usually have as default for our CI4 Models
        return (new ProjectionsModel())->getSum();
    }
}

Question 3. Why we have moved from the logic that we had before with custom queries and version 1?

Long story short: The older way was producing lot of bugs and you didn’t have the freedom to really add your custom queries without a hack. For example the example that you’ve referred to:

$this->db
->select('sum(cost) as our_sum')
...
$output = $crud->render();

may work but for example if the total items was different from your query then there was not even a work-around to fix that with the old custom models.

Keep in mind that even Codeigniter framework realised that and they’ve refactored the way that they use the db builder. Trust me on that, the old db way was fast and it was just working but it was causing lot of issues when we had only one query that you could run at the time so personally I think Codeigniter team did the correct thing anyway :wink:

I hope my above details helped a little bit.

Regards
Johnny

Thank you so much Johnny I will test it out and let you know!