4

I am creating a set of REST APIs to be exposed to my mobile apps using laravel repository pattern.I am using dingo as the REST framework.I am confused on how the response for the APIs should be done using a transformer.

I have the below controller function

if(!$user) { 
    //Authenticate with Twitter and authenticate
    //Register user and issue jwt
    $user = Sentinel::register($device_details);
    $user_data = json_decode($user,true);
    $device_details['users_id'] = $user['users_id'] = $user_data['id'];
    $this->device_details->create($device_details);             
}
$token = JWTAuth::fromUser($user);
$user_array = $user->toArray();
$user_array['token'] = $token;   //An array containing user details and token
return $this->response->item($user_array, new UserTransformer)->setStatusCode(200);   //I can only pass an object (eloquent) as the #1 parameter

My Tranformer class

namespace App\Api\V1\Transformers;

use App\User;
use League\Fractal\TransformerAbstract;

class UserTransformer extends TransformerAbstract {

    public function transform(User $user)
    {
        return [
            'users_id'     => (int) $user->users_id,
            'AUTH-TOKEN'   => $user->token // Doesnt comes from database,
...
        ];
    }
}

Now my question is,

  1. I can only use eloquent objects with a tranformer?
  2. Here in this case, the token is generated by jwt library and I binded it with the array as a single user array. Now how will be able to pass this array to a presenter.
  3. The documention for fractal transformer doesn't say about passing array to the presenter.My data might not always comes from an eloquent object.
  4. How do I handle this case?
  5. Why are presenters used? I would either use a presenter or a tranformer right?
borracciaBlu
  • 4,017
  • 3
  • 33
  • 41
Ajeesh
  • 5,650
  • 8
  • 30
  • 52

2 Answers2

5

You're mixing up a couple concepts here I guess. A presenter is tied to the repository pattern, I don't see anything regarding that in your sample code but I'm assuming you're using it.

A presenter/transformer is nothing more than a layer that casts data from one structure into the other. A transformer layer is useful when you want to make sure your API always returns the same structure regardless if the underlying data object changes.

So, for clarity if you really want to follow the repository pattern the correct way to go is for the presenter to return a transformer. But don't over complicate things.

You can use whatever you want to transform, you can also transform an array into another array but then you have to make sure the parameter accepts that. For example this:

public function transform(Array $user){
    return [
        'user_id'     => (int) $user['id'],
        'auth_token'  => $user['token']
    ];
}

I see you're using Dingo and using it in Laravel 5. So try to modify your dingo response to be:

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

Also make sure that JWTAuth::fromUser($user); can read the $user object/array that Sentinel returns.

tomvo
  • 1,409
  • 1
  • 12
  • 21
0

I have check your code, Please check below code that might work for you. You have to pass $user without converting to array :

if(!$user) { 
             //Authenticate with Twitter and authenticate
            //Register user and issue jwt
            $user = Sentinel::register($device_details);
            $user_data = json_decode($user,true);
            $device_details['users_id'] = $user['users_id'] = $user_data['id'];
            $this->device_details->create($device_details);             
           }
   $token = JWTAuth::fromUser($user);
   $user_array = $user->toArray();
   $user_array['token'] = $token;   //An array containing user details and token
    $user->token = $token;
   return $this->response->item(UserTransformer::transform($user))->setStatusCode(200);   //I can only pass an object (eloquent) as the #1 parameter
Bhavin Solanki
  • 4,740
  • 3
  • 26
  • 46
  • Even though I do that, how will I pass my JWT token? I converted it to an array so that I can add up my token as one of the index in the array an pass the single array to the tranformer. – Ajeesh Dec 19 '15 at 12:29
  • i have Update answer, you can add it using `$user->token = $token;` – Bhavin Solanki Dec 19 '15 at 12:30
  • Thanks. Let me test this out. One more question, are tranformers only used for converting eloquent objects to presentable json? Is it just used for abstracting the database layer? – Ajeesh Dec 19 '15 at 12:32
  • Sorry but i have no idea – Bhavin Solanki Dec 19 '15 at 12:33
  • You can also do one thing: After adding token to `$user_array` , reconvert it to object – Bhavin Solanki Dec 19 '15 at 12:53
  • Hi @Bhavin Solanki I got an error 'Non-static method App\Api\V1\Transformers\UserBankAccountTransformer::transform() should not be called statically, assuming $this from incompatible context' when I used it this way 'return $this->response->item(UserBankAccountTransformer::transform($account));' Ignore the class names wrt the question. Any ideas why – Ajeesh Dec 24 '15 at 15:08
  • Might be you have not define : public function – Bhavin Solanki Dec 24 '15 at 15:13
  • I have this function 'public function transform' in the transformer class. It still throwing error.As per the documentation I tried using ' return $this->response->item($account, new UserBankAccountTransformer);' But its giving output which is not transformed :( – Ajeesh Dec 24 '15 at 15:17