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

Dally's avatar
Level 1

How to use conditional WHERE in raw queries like in eloquent

This is more of a theoretical question. How can you use conditions in a raw laravel query like you do when using eloquent? With simple queries this is not a problem as you can write the query in eloquent but with more complex queries, this would be a nice feature to have (I'm unsure whether it exists or not).

Here is a very simple example. The Eloquent version works but the raw version won't. If this were to be done using a raw query, how would you do it?

Eloquent...

$query = Transaction::orderBy('processingTime', 'desc');

if(isset($request->search['status'])) {
   $query->where('status', '=', $request->search['status']);
}

$query->get();

Raw...

$query = DB::select('SELECT * FROM transactions ORDER BY processingTime DESC');

if(isset($request->search['status'])) {
   $query->where('status', '=', $request->search['status']);
}

$query->get();

The reason I'm asking this question is because I was facing this problem yesterday with a complex query and managed to solve it using collections but I can't help thinking there is an easier more efficient way of doing this. Here's how I solved it last night.

$report = collect(DB::connection('mysql2')->select("SELECT
            t2.holder,
            t2.merchantTransactionId,
            t2.bin,
            t2.last4Digits,
            t3.expDate,
            (CASE WHEN t3.expDate < CURDATE() THEN 'Expired'
            WHEN t3.expDate > CURDATE() THEN 'Due to expire' END) AS expInfo,
            t2.uuid
            FROM transactions AS t2
            INNER JOIN (
                SELECT t1.uuid, t1.holder, t1.bin, t1.last4Digits, LAST_DAY(CONCAT(t1.expiryYear, t1.expiryMonth, '01')) AS expDate
                FROM transactions t1
                JOIN (SELECT t1.merchant_access
                        FROM total_control.users, 
                        JSON_TABLE(merchant_access, '$[*]' COLUMNS (
                            merchant_access VARCHAR(32) PATH '$')
                        ) t1
                        WHERE users.id = :userId
                        ) AS t2
                    ON t1.merchantUuid = t2.merchant_access
                WHERE t1.paymentType = 'RG'
                AND t1.status = 1
            ) t3
            ON t2.uuid = t3.uuid
            WHERE t3.expDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND DATE_ADD(CURDATE(), INTERVAL 30 DAY)
            GROUP BY t2.holder, t2.bin, t2.last4Digits
            ORDER BY t2.holder ASC", ['userId' => $request->userId]));

if(isset($request->search['holder'])) {
    $filtered = $report->filter(function($value, $key) use ($request) {
        if(strpos(strtolower($value->holder), strtolower($request->search['holder'])) !== false) {
            return $value;
        }
    });
    return $filtered->all();
}
0 likes
2 replies
Dally's avatar
Level 1

That works for simple queries but look at the 3rd example I've posted in my original post. That kind of query is best left raw but how can you add further conditions to it if you wish to filter further.

Please or to participate in this conversation.