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
userin thecontroller, so i don't think you need to calluserfor eachfavouritesagain in theFavouriteTransformer. You can simply use this to include theuserFractal will see that, the
useris already exist, so it won't call db query to grab the data.