CodeIgniter Forums

Full Version: Is a beforeFind on a Model a bad idea?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Reworking one project into a pure front/back-end solution with a REST API in CI4 I have been thinking about a way to implement searching and paging of the data returned by find. I have currently a working solution by creating a clone of Model::findAll() and handling paging there. Working, but not the nicest maybe.
Thinking about other possibilities, I wonder why there isn't a beforeFind event where I can get access to the QueryBuilder object to allow manipulation of the find parameters.
What am I missing?

This was actually one of the things that bothered me when I started using ci4. The base model I used to use back in ci3 also had callbacks and it had before and after find. Don't really know why ci4 have all the callbacks built in except this one.
I think I sort of have worked around this. I created a new BaseModel containing the logic for certain things:

PHP Code:

namespace App\Models;


BaseModel extends \CodeIgniter\Model

    protected $useTimestamps true;
    protected $useSoftDeletes false;

    * Handle pagination with
    * @return JsonStoreResponse
    public function getVirtualStoreData()
        $request Services::request();

        $start $request->getGetPost('start');
        $limit $request->getGetPost('limit');

        $builder $this->builder();

        $sql str_replace('SELECT''SELECT SQL_CALC_FOUND_ROWS'$builder->getCompiledSelect());
        echo $sql;
        $query $this->db->query($sql);
        $row $query->getResult($this->tempReturnType);

        $query $this->db->query('SELECT FOUND_ROWS() AS `total`');
        $res $query->getRowObject();

        $result = new JsonStoreResponse(true$res->total);

        return $result;

    * Check the item_version of the new data and make sure the data is in sync between
    * front- and back-end before updating.
    * @param $id
    * @param $new_data
    * @return bool
    * @throws \ReflectionException
    public function validateVersionAndUpdate($id$new_data)
        $record $this->find($id);

        // Ext JS increments the item_version by one when saving.
        // item_version - 1 must match what we have in database, otherwise another edit
        // has been made and we bail out.
        if ((int)$new_data->item_version !== (int)$record->item_version) {
            return false;

        return true;

All my models then extend from this BaseModel and get access to common functions without using events.
Working so far...
(06-29-2020, 10:29 PM)tgix Wrote: [ -> ]What am I missing?


It is possible to define custom events. The (static) class method Events::on() allows you to register an event using any name you like.

File: /app/Config/Events.php

PHP Code:
Events::on('before_findAll', [$modelInstance'modelMethod']);  // Call modelMethod on an existing Model instance 

At the appropriate logical spot in your code, something like this

PHP Code:

You can pass other arguments in trigger if needed.

Events Docs
I never found a consistent use for a beforeFind event, honestly If people feel it's useful then feel free to submit a PR.

For things like searching and filtering for an index page you can always chain methods together. Something like:

In controller:
PHP Code:
$users $userModel->filter($this->request->getPost())->paginate(20); 

and the new method in the model might be something like:

PHP Code:
public function filter($params
$params['search'] && ! empty($params['search'])) {
$params['city_id'] && ! empty($params['city_id'])) {

// Sorting
$sortBy = isset($params['sort']) && trim($params['sort'] !== '')
$sortDir = isset($params['sort_dir']) && in_array($params['sort_dir'], ['asc''desc'])


(06-30-2020, 12:02 PM)kilishan Wrote: [ -> ]For things like searching and filtering for an index page you can always chain methods together.

Thanks. By creating the BaseModel and then extending all my models from that base I think the code is pretty clean and contained in the Model to offload the Controllers.
Doing a project into a front-end / backend solution with the REST API in CI4 I've been thinking of a way to optimize the availability and paging of data returned by search.We are here.  I have a current working solution by creating a clone of Model :: FindAll () and maintaining paging there. Seriously, but not the best either.
Could everyone invested in this thread please check out my beforeFind PR and provide any feedback before it is merged?