Laravel - Fractal - Using Find() in transformer file- is it correct or can it be done more efficiently?

202 Views Asked by At

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.

1

There are 1 best solutions below

0
On

You already eager-load the user in the controller, so i don't think you need to call user for each favourites again in the FavouriteTransformer. You can simply use this to include the user

return $this->item( 
        $favourites->user, new UserTransformer 
    );

Fractal will see that, the user is already exist, so it won't call db query to grab the data.