I have an API resource called FilmResource
, I've appended a new attribute to the model called is_new
and I've added this new attribute to the resource file, the issue is I have two endpoints that make use of this API resource and it's returning the attribute for both but I only want it returned for one method, is there a way you can specify certain keys to be returned in a response? if I use makeVisible
it makes no difference because it's only going from the API resource.
FilmController
This is the method I want it returning for, I've another method which is similar but I don't want it returned for that.
public function show(string $id)
{
$film = Film::findOrFail($id);
return new FilmResource($film);
}
FilmResource
public function toArray($request)
{
return [
'id' => $this->id,
'description' => $this->description,
'name' => $this->name,
'is_new' => $this->is_new
}
Does API resources override what attributes you set within your hidden/visible arrays?
Can you specify you want to hide a key from API resource when you return it in your controller?
Let me exemplify on how to solve your problem by using two different api resources.
In this example, when creating a Film (api store method), we will show all fields, but when visualizing (api show method) we will show just a few fields:
namespace App\Http\Resources\Film;
use Illuminate\Http\Resources\Json\JsonResource;
class Store extends JsonResource {
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'description' => $this->description,
'name' => $this->name,
'is_new' => $this->is_new
];
}
}
And
namespace App\Http\Resources\Film;
class Show extends Store {
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return Arr::except(
parent::toArray($request),
[
'is_new'
]
);
}
}
Note that we are writting from the most complete response to the less complete, so I've only one class with the full definition on how to output the data, and other classes uses it by removing some fields (and also could do any transformations needed).
The other way I suggested is by using the request to know what to show but I don't like this solution because it's not fully decoupled, your Resource will need to know about your routes, and it's not his job IMO.
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Film extends JsonResource {
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$data = [
'id' => $this->id,
'description' => $this->description,
'name' => $this->name
];
if ($request->isMethod('post')) {
$data['is_new'] = $this->is_new;
}
return $data;
}
}
The logic used on my examples are just examples, you might need to adapt to your own needs and create your own logic.