If you want a custom attribute to be appended to the "trips" objects when queried: I recommend using a custom attribute that you can "always" load with your models, or on-demand.
You can define a trip_status attribute, and rename your method to getTripStatusAttribute and it'll be added to the resulting trips queried.
Note that this will NOT affect the main trips SQL query. But will add a travel query for each resulting trips, if travel are not eager loaded. And can be resource greedy as you use a SQL count on a relation every time a trip is loaded (always or on-demand as said).
You can also query your trips using withCount to eager load the travel count with the trip query. And base the trip_status accessor method on the queried count attribute. Still can belong with a heavy database, so prefer to load the attribute only when needed.
You can use withCount with conditions (also see), and use it in accessor:
$posts = Post::withCount('upvotes')
->having('upvotes_count', '>', 5)
->get();
Second note: you can add the travel count to the trip query result, but I don't think that you can add a trip_status only using SQL. A Laravel attribute would be the way to go, by taking care of performance (load travel if needed relationLoaded, use withCount...)
Edit 2: after seeing your comment I am using Yajra Datatables and creating a custom filter for the non-exisiting dynamic status column
you cannot make SQL query against the trip_status as it's not a database. You could filter a collection with ALL the trips on the trip_status, but it's a no go for performance: you need a eloquent/SQL query.
But as I explained, you can query with custom withCount, and so reproduce your needs.
So for the GET data part, I would use the custom attribute.
But for the query part, in a datatable, I would filter my query based on the frontend filters. So you'll need a query based on multiple eager loaded counts (check all the link snippets logic to "mix" them).
Here what a query could look like (not tested fully, but tested the eloquent/SQL part to check for results):
//here you can add other query filters
$trips = Trip::query();
if($frontend_filter === 'canceled') {
$trips = $trips->where('is_canceled', 1);
}
elseif($frontend_filter === 'open') {
$trips = $trips::withCount([
'travels',
'travels AS opened_travel_count' => function ($query) {
$query->where('travels.status', '=', 'open');
}
])
->having('travels_count', '=', 'opened_travel_count'); //careful: will match 0
}
elseif($frontend_filter === 'finished') {
$trips = $trips::withCount([
'travels',
'travels AS finished_travel_count' => function ($query) {
$query->where('travels.status', '=', 'finished');
}
])
->having('travels_count', '>', 0) //could use whereHas travels
->having('travels_count', '=', 'finished_travel_count');
}
elseif($frontend_filter === 'started') {
$trips = $trips::withCount([
'travels', //useless
'travels AS started_travel_count' => function ($query) {
$query->where('travels.status', '=', 'started');
}
])
->having('started_travel_count', '>', 0); //could use whereHas travels where travel
}
//pagination, global eager loads, selects etc...
//you have the pre-filtered query to pass for pagination and stuff
//$trips = $trips->get(); //this gets all and should NOT be used for a datatable
statuscolumn to be accessable and filterable anywhere in my code, and the only way is to convert the php code to a native sql one.statusisn't actually a column, I don't think there is a solution that allows you to naively consider it a regular column elsewhere in your code (assuming you want to do something likeTrip::where('status', 'canceled')->get()). If you give some specific instances of how you want to use thisstatusvalue elsewhere, we might be able to come up with a different/least painful solution. Off hand, using a local scope seems like a good place to look.Student::select()->addSelect(DB::raw('CONCAT(first_name," ", last_name) as full_name'))where full_name became a regular column in the query that I can filter the results with, directly from my frontend table, where the situation is more complicated.statuscolumn.