I have 2 tables: customers and customer_consent_records. As the names imply, the one is just simple customer records, the other contains consent records. The consent records can be for 'News', 'Offers' etc and can be true (consenting) or false (not consenting). A customer can have many consent records.
I want to create a scope that joins the 2 tables on the customer ID, AND the newest consent record that is 'true' AND for a given type ('News').
I have a working query in SQL, I need to replicate this in Eloquent.
Here is the SQL:
SELECT c.id, c.last_name, c.first_name, ccr.id, ccr.consent
FROM customers AS c
LEFT JOIN customer_consent_records AS ccr ON ccr.customer_id = c.id
AND ccr.type = 'News'
AND ccr.consent = 1
WHERE
ccr.id = (
SELECT MAX(id)
FROM customer_consent_records
WHERE customer_id = c.id AND type = 'News' AND consent = 1
)
So far I have the following in my Customer model:
/**
* Scope - customers who have consented to receive the newsletter / wants / interests.
*/
public function scopeConsents(Builder $query, $type = null): void
{
$query->leftJoin('customer_consent_records', function (JoinClause $join) use ($type) {
$join->on('customers.id', '=', 'customer_consent_records.customer_id')
->where('customer_consent_records.type', '=', $type)
->where('customer_consent_records.consent', '=', '1');
})
->where(function (Builder $q) use ($type) {
$q->selectRaw('max(id)')
->from('customer_consent_records')
->whereColumn('customer_id', 'customers.id')
->whereColumn('type', '=', $type')
->whereColumn('consent', '1');
});
}
But when I run this query:
$customers = App\Models\Customer::select('customers.id', 'customers.last_name', 'customers.first_name')->consents('News')->limit('100')->toRawSql();
return dd($customers);
I get the following SQL:
select
`customers`.`id`,
`customers`.`last_name`,
`customers`.`first_name`
from
`customers`
left join `customer_consent_records` on `customers`.`id` = `customer_consent_records`.`customer_id`
and `customer_consent_records`.`type` = 'News'
and `customer_consent_records`.`consent` = '1'
where
(
`customer_id` = 'customers.id'
and `type` = `News`
and `consent` = '1'
)
limit
100
It seems to be ignoring the selectRaw entirely. Any suggestions on what I'm doing wrong?
Thanks,
Steve