Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

t0berius's avatar

laravel collection filter with where()

After inspection some code I noticed a strange behaviour when it comes to fitering a collection:

        $relatedOrder = $orders->where('id', $uniqueID)
            ->filter(function ($order) use ($txid) {
                return $order->orderTransactions
                    ->where('txid', $txid)
                    ->where('is_confirmed', false);
            });

After running the code it seems like the filter() part is not respected in any bit. Only the check of where('id', $uniqueID) is being respected.

I can even replace parts of code like:

        $relatedOrder = $orders->where('id', $uniqueID)
            ->filter(function ($order) use ($txid) {
                return $order->orderTransactions
                    ->where('txid', "sometext")
                    ->where('is_confirmed', true);
            });

and the result would be the related mode, only filtered by $uniqueID.

I want to filter the orders by using the first where('id', $uniqueID) and the filter() part, not only once of both, can somebody please take a look and explain what's going on here?

0 likes
3 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

It seems like there might be a misunderstanding of how the filter method works in combination with the where method on a Laravel collection. The filter method expects a closure that returns a boolean value to determine if an item should be included in the resulting collection. However, in the provided code, the closure is returning a collection (or a builder) from the where method calls, which is truthy even if it's empty, so the filter isn't actually filtering anything out.

To fix this, you should return a boolean from the closure by checking if the collection returned by the nested where calls is not empty. You can use the isNotEmpty method for this purpose.

Here's the corrected code:

$relatedOrder = $orders->where('id', $uniqueID)
    ->filter(function ($order) use ($txid) {
        // Check if the order has any transactions that match the criteria
        return $order->orderTransactions
            ->where('txid', $txid)
            ->where('is_confirmed', false)
            ->isNotEmpty(); // This will return true if there's at least one transaction matching the criteria
    });

With this change, the filter method will correctly include only those orders that have at least one transaction with the specified txid and where is_confirmed is false.

1 like
Snapey's avatar

filter is not a valid query builder method. It is a collection method and can only work on the data once you have fetched it from the database into memory

tykus's avatar

This will always be truthy (assuming orderTransactions is a Collection)

return $order->orderTransactions
                    ->where('txid', $txid)
                    ->where('is_confirmed', false);

Even an empty Collection object will be truthy, so the filter has no effect. If you are trying to filter out Order instance where there are no matching transactions, then you need to check the size of the orderTransactions collection after the wheres

1 like

Please or to participate in this conversation.