How to return HTTP status code when returning a ResourceCollection in Laravel - laravel

I'm building an API and I'm trying to return a ResourceCollection for a Classroom in Laravel.
Previously I used an array of classrooms and returned a response with the array and the status code, like this:
$classrooms=Classroom::all();
return response()->json($classrooms,200);
Now this is my code:
$classrooms = new ClassroomCollection(Classroom::paginate(10));
return $classrooms;
to get this response:
"data": [classrooms array],
"links": {
"first": "http://127.0.0.1:8000/api/classrooms ?page=1",
"last": "http://127.0.0.1:8000/api/classrooms ?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": null,
"last_page": 12,
"path": "http://127.0.0.1:8000/api/classrooms ",
"per_page": 10,
"to": null,
"total": 0
}
and I can't find a way to send a status code along with the ClassroomCollection, because if I do
return response()->json($classrooms,200);
I'm only returned the "data" object, without the links and meta of the paginator.
Any help?

you can override the withResponse function in your collection like this:
public function withResponse($request, $response)
{
if($response->getData()) {
$response->setStatusCode(200);
} else{
$response->setStatusCode(404);
}
parent::withResponse($request, $response);
}

If you really want to you can do the following:
return response()->json($classrooms->jsonSerialize(), 200);
->jsonSerialize() does not actually serialize as a JSON string but returns an array that can be serialized to JSON string. Laravel serializes to a JSON response if you return an array or JsonSerializableable object from a controller/route and that is what the paginator implements.
However, if 200 is the status code you want, that is implied and the default status code and there is no need to supply it.
So the above is equal to:
return $classrooms;

Related

VueJs not sending data via Inertia to Laravel?

I have question it seems like when I try to send some data via Inertia I dont recieve any in Laravel for some reason any suggestion? Can it have to do something with the fact that the object is proxy object ?
Here are some images:
dd() in php controlelr
console.log() of the object before beeing sent via Inertia
Code of how I send the data + the console log right before sending it
UPDATE:
This is how I add page object to array of pages:
this.Pages.push({
"name": "Untitled",
"icon": "home",
"order": order,
"sections": [],
"DisplayName":true,
"Banner":"Medium",
"Published":"Published",
"DisplayLogo":true,
"media":{
'BackgroundImage': null,
'LogoImage': null,
'BackgroundImageHeight': null,
'LogoImageHeight': null,
'BackgroundImageStyle': {
"value": []
},
"LogoImageStyle": {
"value": []
},
}
});
This is my inertia form:
saveForm: {
applications: [],
},
This is whole save() method:
Save() {
if(this.localProduct.translation.applications.mobile_label[this.currentMobileLabel] != undefined){
if(this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].data == undefined){
this.localProduct.translation.applications.mobile_label[this.currentMobileLabel] = {
"Pages": this.Pages,
"media": this.media,
"name": this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].name,
"active": this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].active,
};
}
else{
this.localProduct.translation.applications.mobile_label[this.currentMobileLabel] = {
"Pages": this.Pages,
"media": this.media,
"name": this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].name,
"active": this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].active,
"data" : this.localProduct.translation.applications.mobile_label[this.currentMobileLabel].data,
};
}
}
this.saveForm.applications = toRaw(this.localProduct.translation.applications);
console.log(this.saveForm);
Inertia.post(this.route(`product.translations.applications`,{translation: this.localProduct.translation.id}),this.saveForm);
},
The applications should be array, the mobile_label should be also array.As it is.
!!!IMPORTANT ALSO!!!
All of this code worked before the project started to shift to vue js 3 and I suppose many libraries had to be updated/exchanged for others.
According to Inertia's documentation the first parameter expected when using Inertia.post() is a URL. Does all of this.route(`product.translations.applications`,{translation: thislocalProduct.translation.id}) return a URL?
To anyone who's having same problem check your array/object assiging to your variables there could be the mistake like in mine I fixed mine with this:
this.saveForm.applications = toRaw(this.localProduct.translation.applications);
var fixed = Object.assign({},this.localProduct.translation.applications);
Inertia.post(this.route(`product.translations.applications`,{translation: this.localProduct.translation.id}),fixed);

How to handle JSON array response while using APIConsumer?

Using the APIConsumer contract we can feed data from API to the smart contract.
Eg: If the server response is:
{
"RAW":{"ETH":{"USD":{"VOLUME24HOUR": 10000,}}}
}
Then, data can be obtained as:
request.add("get", URL);
request.add("path", "RAW.ETH.USD.VOLUME24HOUR");
Similarly, If the server response contains some JSON array,
Eg:
{
"date":"530934083405834",
"results": [
{
"id": 9865,
"rank":1
},
{
"id": 9869,
"rank": 2
},
{
"id": 9866,
"rank": 3
}
]}
Then in this case is there a way to get the id of the rank 1 i.e results[0]["id"]?
To get results[0]["id"] your path in the request needs to be
request.add("path", "results.0.id");

How to receive this json data and insert in db

Post this data from app.how to receive this data in Controller and Insert DB
{
"status": "processing",
"customer_id":"30",
"shipping_address":{
"first_name":"",
"last_name":"",
"address":"",
"city":"",
"state":"",
"postcode":"",
},
"items":[{
"product_id":61,
"quantity": 1
},
{
"product_id":62,
"quantity": 1,
}]
}
To get the data to Controller just use $this->input->post('name');
You can use json_decode() function to decode your JSON.
Check out this link : Json decode
Use json_decode($data,true); in controller. $data could be post data and this will resulting into an array.

Send multiple variable to laravel Api resources

I want to different type of collection..One containing users acros the city and another one containing near by users. I want these from single api hit. is it possible ? If yes then please suggest how to do that.
Waht I did
return ServiceProviderCollection::collection($near_by);
Output:
"data": [
{
"username": "??",
"email": "??",
"rating": 0,
"role_id": 2,
"wallet": "0"
}
],
I want
return ServiceProviderCollection::collection($near_by,$across_city);
expected output:
{
"across_city": {
"data": [
{
"username": "??",
"email": "??",
}
],
},
"near_by": {
"data": [
{
"username": "??",
"email": "??",
}
],
}
}
No, you can't pass 2 objects in Resource. You can do it like this
return [
'across_city' => ServiceProviderCollection::collection($across_city),
'near_by' => ServiceProviderCollection::collection($near_by)
];
Edit: After comment
If you want to show pagination information then you have to create separate controller action and then return ServiceProviderCollection::collection then you will get result with pagination meta information.
create these action in your controller ex. (UserController)
public function acrossCity(){
$acrossCity = User::where('city','test')->paginate(10); //example
return ServiceProviderCollection::collection($acrossCity);
}
public function nearBy(){
$nearBy = User::where('near','1')->paginate(10); //example
return ServiceProviderCollection::collection($nearBy);
}
create routes for these
Route::get('user/acrossCity','UserController#acrossCity');
Route::get('user/nearBy','UserController#nearBy');
Check document https://laravel.com/docs/5.6/eloquent-resources#pagination
Note: when using resource class then name it without Collection. For your case you should name resource as ServiceProviderResource and then when you call its collection then ServiceProviderResource::collection($object) but when returning single object then new ServiceProviderResource($object).
I am currently using Laravel 7 and in my controller I am passing an array of collection objects to resource class
$data = ['quotation' => Quotation::first()];
return new QuotationResource($data);
and in my resource class I can access the data using
public function toArray($request)
{
return [
'quotation' => $this->resource['quotation']
];
}

Laravel Api resource controller json format

I managed to change the format for the json response of the laravel resource controller for APIs, i want to make a key -> value response but i cant find the way to remove the brackets:
the response i get is this:
{
"1": [
{
"updated_at": 1536147154
}
],
"2": [
{
"updated_at": 1536160598
}
]
}
but i want it to be like this:
{
"1":
{
"updated_at": 1536147154
},
"2":
{
"updated_at": 1536160598
}
}
I get the response from an eloquent collection, and then I group it by id, but I don't know how to get rid of the brackets because the values end in an array.
I don't know if I am clear in my question.
Solved it, i removed the groupby and instead, I used the keyBy to assign their id as a key.
Transformers can be used to format json
I used https://github.com/spatie/laravel-fractal to format my json response in controllers

Resources