Search code examples
cakephpormquery-buildercakephp-3.x

How to remove an item from a resultset in CakePHP 3?


I'd like to remove some specified items from a ResultSet which means I need a ResultSet object at end.

Is there any way to remove an item from a ResultSet or create another ResultSet from existing ResultSet?

I've tried using filter() or reject(). But, they don't return a ResultSet object?

$ids = [123, 234, 456];
$results = $this->find()
             ->where(['xxx' => 'xxxx'])
             ->all();

$newResults = $results->filter(function ($result) {
    return in_array($result->id, $ids);
});

Solution

  • I would question whether you actually need a result set, that is an object that implements \Cake\Datasource\ResultSetInterface.

    The result set interface is just a combination of \Cake\Collection\CollectionInterface, \Countable, and \Serializable, which is almost satisfied by CakePHPs regular collection class, ie \Cake\Collection\Collection, it's just lacking \Countable::count(). So the collection returned by your filter() call should satisfy your needs in most cases.

    If for some reason you'd be forced to pass a \Cake\Datasource\ResultSetInterface implementation, and you absolutely cannot change that contract for whatever reason, then you could always pass your data to a new result set decorator:

    $resultSet = new \Cake\Datasource\ResultSetDecorator($collection->toArray());
    

    Also you can manipulate your data on query level, either by simply not retrieving the data that you don't want in the first place, ie exclude them in your where() conditions, or by filtering in a result formatter, then you'll directly receive a reduced \Cake\Datasource\ResultSetInterface object from your query:

    $results = $this
        ->find()
        ->where(['xxx' => 'xxxx'])
        ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
            return $results->filter(/* ... */);
        })
        // ...