Have a look at Fractal: https://github.com/thephpleague/fractal
That looks really interesting. Thanks, I'll give that a shot.
Messing around with Fractal, and I got the basics to work. Just one further question - where's a good spot to initialize the Fractal manager in Laravel? Still pretty new to Laravel.
I have a very similar problem to you - I'm wanting to only return specific columns on many-to-many related objects for an API. After reading this thread I'm now also testing out Fractal, but I'm not having as much luck as you. The documentation doesn't contain a lot of examples so I'm struggling. Do you mind sharing what you've managed to do with Fractal?
In regards to intializing the Fractal manager, I was thinking in the base controller, but I'm also fairly new to Laravel so I say that's probably wrong.
I thought it looked ugly to have both HTML and JSON output in the same controller, so I split it up like this:
I initialize Fractal in BaseController.php for now:
public function __construct()
{
$this->fractal = new Fractal\Manager();
}
I wrote a ContestTransformer.php and stuck it in app/api
, and added the app/api
path to start/global.php
.
<?php
use League\Fractal;
class ContestTransformer extends Fractal\TransformerAbstract
{
public function transform(Contest $contest)
{
$ary = [
'id' => (int) $contest->id,
'owner_id' => (int) $contest->owner_id,
'name' => $contest->name,
'is_public' => (int) $contest->is_public,
'is_finished' => (int) $contest->is_open,
'start_date' => $contest->start_date,
'end_date' => $contest->end_date,
'players' => $contest->players->toArray(),
'events' => [],
];
// Massage events into proper format
foreach($contest->event as $e) {
// ...and this is where I quit last night
}
return $ary;
}
}
/* EOF */
And then I can use it like this in ContestApiController.php:
public function show($contest_id)
{
$contest = parent::show($contest_id);
$resource = new Fractal\Resource\Item($contest, new ContestTransformer);
return Response::json($this->fractal->createData($resource)->toArray());
}
Still a bit messy, but I'm working on cleaning it up.
Oh, and I route it like this:
Route::group(['prefix' => 'api/v0'], function() {
Route::resource('contest', 'ContestApiController');
});
Thank you very much for sharing.. I'm back on track now - very much appreciated.
One small update - I didn't like initializing Fractal in the constructor, so I added this method to the base controller:
protected function toJsonArray($resource)
{
$fractal = new Fractal\Manager();
return $fractal->createData($resource)->toArray();
}
And I call it in the API controllers:
public function show($contest_id)
{
$contest = parent::show($contest_id);
$resource = new Fractal\Resource\Item($contest, new ContestTransformer);
return Response::json($this->toJsonArray($resource))
->setCallback(Input::get('callback'));
}
Instead of doing that, why not use dependency injection? Something like this:
use League\Fractal\Manager;
class ApiController extends Controller
{
public function __construct(Manager $fractal)
{
$this->fractal = $fractal;
$this->fractal->setRequestedScopes(explode(',', Input::get('include')));
}
}
Then just make sure that all your API controllers extend ApiController instead of your usual BaseController. Makes things testable.
Can I do that with my current class setup? Still new to Laravel and "proper" PHP coding, but I'm certainly willing to learn new stuff.
Currently I have:
Don't know what your exact setup is, but I'd probably do it like that:
@jsvensson Did you figure out how to access the score data one level up?
For anyone bumping on this thread like me: Take a look at this post.
Especially this part:
public function products()
{
return $this->belongsToMany('Product')
->withPivot('desired_column as desired_column');
// this way you override aliasing the column to pivot_desired_column
// thus avoid it being attached to the pivot model
}
You then access desired_column
like this:
$model->products()->first()->desired_column //not first()->pivot->desired_column
The same is reflected in the JSON response which would solve the OPs problem.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community