Hello,
As I am building up my JSON API, I’ve run into a design decision/problem I need to make.
Assume I have a model of Car
s, where is Car
is associated (belongsTo) a User
. So, I can receive a response about a car with id:1001 like so:
GET /api/cars/1001
This contains a owner_id
which points to the User
. But I also want to include some additional user info in the response, like the user_name
, to make the API easier to consume.
I found several ways of approaching this, but I am not sure which is the best.
- Eloquent Eager Loading
I could do something like this in the controller class: Car::with('user:id,user_name')->find($id);
Works fine, two minor(?) issues: 1. The user info appears as a sub-object in the response, 2. The user id field appears in the user object, which is redundant, and it’s already repeated as a foreign-key in the response.
- Local Scope
I can define a local scope in the Car
model, something like this:
public function scopeGetUserDetails($query) {
$query->addSelect('cars.*');
$query->leftJoin('users as owner', 'owner.id', '=', 'cars.owner_id')->addSelect('owner.user_name as owned_by_username');
return $query;
}
Then, in my controller I call this like so: $car = Car::getUserDetails()->find($carID);
The good thing is that the owned_by_username
will appear at the root level of the response. Which looks clean.
The bad thing is that the Car
model pokes around with the database structure, and leftJoins the users table by name, which kinda breaks encapsulation the models provide.
- There is a third way using
Accessor
methods in the Model. But this seems to be very inefficient because extra separate queries will need to be fired to the database to get the extra fields.
So there… open to all your wisdom on how to approach this problem. Thanks!