So, I am using Laravel 5 and Fractal to add presentation and transformation layer for my data output and was wondering what I am doing below is correct or overkill.
I have Users table and Favourites table and I want my JSON to be outputted like below:
Note: Pay close attention to profile_id and id in the nested data. I basically want my favourites and within those the user's details (from Users table) that I have favourited.
Below, I have favourited profile_id 404 and his details (from users table) is nested too.
"data": [
{
"id": 15,
"user_id": 231,
"profile_id": 404, <------------------------ HERE
"created_date": "2013-04-10 21:35:28",
"user": {
"data": {
"id": 404, <------------------------ HERE
"username": "hugeheart12",
"has_photo": 1
}
}
},
{
"id": 64,
"user_id": 231,
"profile_id": 1085, <------------------------ HERE
"created_date": "2013-06-17 08:14:02",
"user": {
"data": {
"id": 1085, <------------------------ HERE
"username": "snowbird37",
"has_photo": 1
}
}
}
Users
id (PK)
name
username
email
created_date
Favourites
id
user_id
profile_id
created_date
Users Model
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Support\Facades\DB;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
public function favourites()
{
return $this->hasMany('App\Favourites', 'profile_id', 'id');
}
public function photos()
{
return $this->hasMany('App\Photos', 'user_id', 'id');
}
Favourite Models
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Favourites extends Model {
protected $table = 'favourite';
public function user()
{
return $this->belongsTo('App\User', 'from', 'id');
}
}
This is what I have in my controller:
$favourites = Favourites::with('user')->where('profile_id', '=', 231)->get();
$resource = new Fractal\Resource\Collection($favourites , new FavouriteTransformer());
return $this->respond(
$this->fractal->createData($resource)->toArray()
);
FavouriteTransformer
<?php
namespace App\Mmh\Transformer;
use App\Favourites;
use League\Fractal;
class FavouriteTransformer extends Fractal\TransformerAbstract
{
protected $defaultIncludes = [
'user'
];
public function transform(Favourites $favourites)
{
return [
'id' => (int)$favourites->id,
'user_id' => (int)$favourites->user_id,
'profile_id' => (int)$favourites->profile_id,
'created_date' => $favourites->created_date,
];
}
public function includeUser( Favourites $favourites )
{
return $this->item(
$favourites->user->find($favourites->profile_id), new UserTransformer
);
}
}
Look at the last return return $this->item( $favourites->user->find($favourites->profile_id), new UserTransformer );
All that code above gives me the JSON above but is there any way of doing this a better way or the way I am doing it is correct? Something tells me there must be a better way of doing this than querying the database for every item but I don't know how.
Thank you for reading.
You already eager-load the
user
in thecontroller
, so i don't think you need to calluser
for eachfavourites
again in theFavouriteTransformer
. You can simply use this to include theuser
Fractal will see that, the
user
is already exist, so it won't call db query to grab the data.