Reputation: 1908
User scans barcode and system responses with a barcodable model (can be Article, Package or Inventory Shelf).
return new BarcodeResource($barcode);
Barcode resource resolves barcodable resource based on barcodable class. Each barcodable model return different JSON resouce.
// BarcodeResource.php
$modelResource = app()->makeWith(__NAMESPACE__ . '\\' . class_basename($this->barcodable) . 'Resource', [
'resource' => $this->barcodable
]);
return [
'code' => $this->code,
'model_type' => class_basename($this->barcodable),
'model_data' => $modelResource
];
In case of...
I want to prevent infinity loops with recursive resources.
Article
>> Package
>> Article (infinity loop begins because package resource
returns articles in spesific package)
Package
>> Article
>> Package (loop...)
>> Inventory Shelf
>> Package (loop...)
>> Child package
Inventory Shelf
>> Package
>> Article
>> Inventory Shelf (loop...)
>> Child package
Eager loading and unsetting relations should be one solution, but how I can unset those in the correct phase? Is this even possible with one resources or should I make multiple resources (recursive/normal)?
I tried this solution, but magically $this->relations
attribute gets changed to integer 1 after couple recursions...
class PackageResource extends JsonResource
{
private $relations;
public function __construct($resource, array $relations = [])
{
parent::__construct($resource);
$this->relations = $relations;
}
public function toArray($request)
{
return [
'id' => $this->id,
'articles' => $this->when(in_array('articles', $this->relations), ArticleResource::collection($this->articles, $this->relations)),
'children' => PackageResource::collection($this->children, $this->relations),
];
}
Upvotes: 2
Views: 129
Reputation: 1081
My solution for a similar situation was as follows:
In the Resource files, I allways return relationships based on a request property with
. This is attached to the request as follows:
I need the User
with Orders
and Profile
, but I also need the Area
for an order, than the request is something like this:
http://example.com/api/v1/user/234?with=user.orders,user.profile,orders.area
and in the Resource file something similar:
public function toArray($request)
{
$return = [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'location' => $this->location,
'active' => $this->isActive(),
'level' => $this->level,
];
if($request->has('with')){
$relationships = [
'orders'=>[OrderCollection::class, 'orders'],
'area'=>[Area::class, 'area', 'area.admin'],
'profile'=>[UserProfile::class, 'profile'],
];
$with = explode(',', $request->with);
foreach($relationships as $key => $relationship){
if( in_array("user.".$key, $with) ){
$return[$key] = new $relationship[0]($this->{$relationship[1]});
}
}
}
$return['created'] = $this->created_at->toDateTimeString();
return $return;
}
An other solution is to add an extra property to the resource class:
protected $with = "";
public function __construct(mixed $resource, $with="")
{
parent::__construct($resource);
}
Than, when you call that resource, you can filter it in the previous way. I just tested and it worked for me.
Hope that helps.
Upvotes: 1