In lumen 8 app I use resources and reading here https://laravel.com/docs/8.x/eloquent-resources
I try to use “with” method, as I want to add some meta data to any request and I have no this meta data in returned data :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Models\Page As PageModel;
use App\Http\Resources\User as UserResource;
class Page extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
...
'created_at' => $this->created_at,
];
}
public function with($request)
{
\Log::info( '-1 unction with ::' . print_r( 1, true ) ); // I DO NOT SEE THIS LOGGINHG line
return [
'meta' => [
'version'=>getAppVersion()
]
];
}
}
In the referenced docs resource is declared a bit different from ResourceCollection:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return parent::toArray($request);
}
public function with($request)
{
return [
'meta' => [
'key' => 'value',
],
];
}
}
Could it be the issue and how can fix my resource to get all meta data ?
Updated block: UserCollection - that is collection https://laravel.com/docs/8.x/eloquent-resources my collection is Page and I use it in controller as :
namespace App\Http\Controllers;
use Carbon\Carbon;
use App\Models\Page;
use Illuminate\Http\Request;
use App\Http\Resources\Page as PageResource;
use Config;
use App\Http\Requests\PageRequest;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Validator;
class PageController extends Controller
{
public function index()
{
$pages = Page
...
->get();
return $this->sendOkResponse(PageResource::collection($pages), '');
}
sendOkResponse defined in Http/Controllers/Controller.php :
class Controller extends BaseController
{
protected $requestData;
public function __construct()
{
$request = request();
$this->requestData = $request->all();
}
public function sendOkResponse($responseResult, $message)
{
$response = [
'success' => true,
'data' => $responseResult,
'message' => $message,
];
return response()->json($response, HTTP_RESPONSE_OK);
}
I suppose PageResource is destroyed at PageController controller index method exit...
Updated block # 2: After some tests I found that Resource method “with” does not work if collection is returned and I need to use ->additional in controller like:
return (PageResource::collection($pages))
->additional([
'meta' => [
'version' => getAppVersion()
]
]);
But in cases when I return sinopgle element(ex store method) like
return (new PageResource($page));
method “with” works ok.
That exludes using of wrapper like sendOkResponse. Is is the only proper way?
Thanks in advance!
Laravel resources are intended to be returned directly from your controller's action method, not as part of an associative array representing JSON.
When wrapping your responses with the sendOkResponse
method, the resource is not being returned directly from the method and thus toArray
is being called on your resource. The with
method on your resources is being ignored.
Try returning the resources directly from your controller's method. Use the additional
method when constructing your resources to pass the extra attributes in the response. See: https://laravel.com/docs/8.x/eloquent-resources#adding-meta-data-when-constructing-resources.
If you can control the API contracts, I'd recommend changing them to omit success
entirely, this can be derived from the HTTP status code.