In Laravel Eloquent, I am using select
to get specific columns only in a collection:
$tickets = Tickets
::select('id', 'title', 'date') // so only these columns
->limit(100)
->get();
but I also have a custom attribute in the "Ticket" model that uses different columns:
public function getStatusAttribute() {
if ($this->payment == $this->total & $this->active) {
return "paid";
} else {
return "unpaid";
}
}
then when doing
foreach ($tickets as $ticket) {
echo $ticket->id
. $ticket->title
. $ticket->date
. $ticket->status // <- custom attribute
;
}
as I tell query to only select ‘id’, ‘title’, ‘date’, at what point Laravel gets additional columns from database (specifically the ‘payment’, ‘total’, ‘active’)? Does it runs additional queries for each row?
I only see main query (without columns from custom attribute being selected), when trying to log them either with dump(DB::getQueryLog());
or directly in MySQL:
SET GLOBAL log_output = "FILE";
SET GLOBAL general_log_file = "c:/AAA/logfile.log";
SET GLOBAL general_log = 'ON';
So I do not understand at what point Laravel gets additional columns from the database? My concern is to have 1 query and not 100.
2
Answers
hope my solution solves your problem.
To ensure the status attribute works correctly, modify your query to include the columns needed for the accessor:y and avoid additional queries.
This way, all the necessary data for the custom attribute is fetched in the initial query.
Thanks
The status attribute is never queried from the DB. The value is calculated after the query is run when you request the value using
$ticket->status
or when the instance of the model is serialised.If you have retrieved your instance using your query builder code:
Then I would expect your
getStatusAttribute
to return"paid"
but you need to understand why:The query will result in an instance where
$this->payment
is NULL$this->total
is NULLand
$this->active
is NULLBecause you’re not getting those values from the database.
When you call
$this->payment == $this->total & $this->active
You’re saying
NULL == NULL & NULL
Note: Be careful with your logic here as
NULL & NULL
will evaluate to0
whereasNULL && NULL
will evaluate tofalse
Therefore you need to either be more defensive in your
getStatusAttribute
logic. You could consider returning NULL if the required columns are all NULL but you probably want to make sure those values are always queried.The above would do the job but the overhead of querying columns you don’t explicitly need is negligible so you could just drop the select entirely and use:
If there are values in there you want to prevent the model showing when serialised I would recommend using the Eloquent Model’s "hidden" property