Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Counting matching find() records
  • I hope this is the right forum: I'm using the crud model. I have a model "Event" that holds events which have been pulled across from an MS Dynamics CRM. The events are stored with various searchable fields such as number numbers of places left on the events, the date the event is on, etc. The package that handles the events has a method getEvents() that takes a number of filters (e.g. 'date_from'=>strtotime('last year'), 'bookable_places'=>true). These all go into a where condition in a find() method:
    $Events = Model_Event::find(array('where' => $my_where, 'limit' => $limit, 'offset' => $offset));
    

    Now, when implementing a pager using the limit and offsets, it is also necessary to get a count of all records that match the query, i.e. that match the where clause. What would be the best way to do that? I'm using this method at the moment:
    $Count = Model_Event::count('id', false, $my_where);
    

    Is that the best way to do it? Or can the find() method be asked to return a count, without actually fetching back all the rows and counting them, obviously. The count should ignore the limit and offset, as it needs to provide the total count of matching records, so you know how many pages there are. -- Jason
  • Do it like this
    $query = Model_Event::find()->where('soemthing', $something);
    $count = $query->count();
    $events = $query->limit(15)->get();
    
  • I thought it would be something like that, but it does not appear to be working for me. My Model_Event::find() is immediately returning an array of fetched model objects, i.e. rows. It is not returning a query object. I'll look a little deeper to see what may be happening here - perhaps my FuelPHP install is a little old, and this action has changed? In my install, the find() method translates to "go get 'em now". -- Jason Edit: the documentation here: http://docs.fuelphp.com/packages/orm/crud.html says: "When you use the find() method without properties it will return an Orm\Query object which you can use, and possibly reuse to find entries." So I'm guessing my crud package is a little old (a few months) and this functionality had not been added then. Edit 2: thinking about it, is that documentation correct? Looking at the latest crud object, the find() method *always* performs an execute() then returns the results in an array. I may be looking at it in the wrong way, but I cannot see how it can return a query object without immediately executing the query and fetching the results. I feel like I am looking at a completely different set of code from everyone else - been through the git history of Model and Model_Crud, and cannot see how it could have ever worked in the way you describe, but I am guessing it must have, at some point.
  • In case it is not clear, my Model_Event is extending "\Model_Crud" not "\Model" from the orm package. Is that perhaps my problem? \Model_Crud replaces the find() method - perhaps wronging ignoring empty parameters when the find() method is called, or perhaps correctly solving a different problem to the one I am trying to solve. -- Jason
  • I have moved from the crud model to the orm model. The two can be very confusing in the docs, since they seem to be doing largely the same thing, use many of the same method names, but the methods of the same name have very different purposes. Now, if I understand correctly, the orm model does not have the handy before_whatever() and after_whatever() methods that can be used to tweak the data as it goes in and out of the database. In the crud model, I was using the before_save() and post_find() methods to serialise and unserialise one of the properties of the object. So I guess I need to look at using an observer to do this with the orm? Essentially, I want to be able to push a complex nested array into the "detail" property of the event object, and save it. When retrieving the object, I would like to get back that complex nested array. The array would actually be stored in serialised form in a text column of the database. I just want the orm object to hide the conversions from the package methods and controllers using that model. Is that what an observer would do? If I need to add a non-database property to the object (detail_expanded, perhaps) to put the array in and out of the object, then that would be fine. I can read up how to use the observers, but just need to be confident this is the right approach before going down that route.
  • Aha - observers are not actually that complicated when put into the model of "self" observers. This is the ideal way to do it when a model has some special data handling that is not likely to be reused in any other orm models, such as for timestamps and slugs. In my orm model, in _event_before_save() I serialise the content of "detail_array" into "detail". In the _event_after_load() method I unserialise the content of the "detail" property into "detail_array". Outside of the model, I just put the big array into the "detail_array" property, and get if from there on retrieval, and that's it. In my orm model:
        // Observers to handle the timestamps, and also the detail serialisation.
        protected static $_observers = array(
            'Orm\Observer_CreatedAt' => array(
                'events' => array('before_insert'),
                'mysql_timestamp' => false,
            ),
            'Orm\Observer_UpdatedAt' => array(
                'events' => array('before_save'),
                'mysql_timestamp' => false,
            ),
            'Orm\\Observer_Self' => array(
                'before_save',
                'after_load',
            ),
        );
    
        // Before saving, move the detail_array property value to the detail
        // property, serializing it on the way.
        public function _event_before_save()
        {
            $this->detail = json_encode($this->detail_array);
        }
    
        // On loading an evenr, set the detail_array property to the decoded version 
        // of the detail property.
        public function _event_after_load()
        {
            $this->detail_array = json_decode($this->detail, true);
        }
    

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion