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.