Using Laravel JSON response inside a __toString method - laravel

I have method in my class that returns a JSON response.
public function response(){
return \Response::json(['data'=>'somedata']);
}
To be able to use more chain methods I want to use the __toString() method whenever I want to return an object as a response. Like this:
public function __toString(){
return $this->response();
}
But I get this error:
Method MyClass::__toString() must return a string value
Which makes sense but how can I do that. I looked in Laravel and Symfony JsonResponse classes and couldn't find a method to fix this. I tried the getContent() but that is just a string not a proper Json response.

After a lot of research I found a solution. I don't know if it is the best but here it is:
public function __toString(){
$this->response()->send();
return '';
}
Which is actually a call to Symfony\Component\HttpFoundation\Response::send() method instead of returning an string.

Thyis is a late response but I found a better solution, letting Laravel handle the response:
public function __toString(){
return Response::json($this)->content() ' Returns a string
}

Related

How to pass request parameter with post method from a controller to another controller method in Laravel?

I want to call the method of B controller from Acontroller.So I used this method
return redirect()->action('UserController#subscribe()');
But here I am facing an issue here. I want to pass below param as in request body to above subscribe()
$package_id = session('package_id');
$package_type = session('package_type');
Please help me out how can I pass above param in request in laravel
If you need to call one controller from another, it seems like you have not so good architecture, and you have to refactor your code.
But, if you anyway want to do it, you can do it like that:
app('App\Http\Controllers\UserController')->subscribe($package_id, $package_type);
Controller 1
public function method1()
{
$package_id = session('package_id');
$package_type = session('package_type');
return app('App\Http\Controllers\Controller2')->method2($package_id, $package_type);
}
Controller 2
public function method2($package_id, $package_type)
{
//
}
You can append them to the query string.
return redirect()->action('UserController#subscribe', [
'package_id' => $package_id,
'package_type' => $package_type,
]);
You can call the controller.
app(UserController::class)->subscribe();

How do I convert an API resource class in Laravel 5.5 to an array BEFORE returning from controller?

Ordinarily, in Laravel 5.5, when using an api resource class, you simply return the resource class instance from your controller method, like so:
public function show(Request $request, MyModel $model)
{
return new MyModelResource($model);
}
This converts the model to an array (and ultimately to json) in the response to the client.
However... I am trying to figure out how to convert everything to an array BEFORE returning it from the controller method. I tried this:
public function show(Request $request, MyModel $model)
{
$array = (new MyModelResource($model))->toArray($request);
// ...
}
The problem here is that any relationships loaded on the resource aren't also converted to an array. They show up inside $array as an instance of a resource class. Obviously calling toArray() manually does not result in a recursive call, and methods such as ->whenLoaded('relationship_name') aren't really respected either.
So how do I get Laravel to do everything it does to convert the resource to an array recursively WITHOUT having to return it from my controller method?
I believe what you are looking for is the resolve method on the resource class. See definition.
From the looks of it, it should handle converting the relationships into an array as well. Just be sure you are setting up your resource relationships properly.
Neither the toArray() or resolve() methods convert the related models to arrays which is really annoying because you'd expect them to.
You're better off using toResponse(null) which will return a JsonRepsonse object. Which you can then use the getContent() method for a json encoded string or the getData() method for an object.
So if you wanted an array not wrapped in a data variable it would be:
$array = json_decode(
json_encode(
(new MyModelResource($model))
->toResponse(null)
->getData()
->data
),
true);
Ugly but it works unlike the accepted answer.

Laravel Eloquent Resource Collection response

So I am trying to use a resource collection to return datatable json information. Before I used my collection I first did a proof of concept that looked like this:
public function index()
{
$clients = QueryBuilder::for(Client::class)
->allowedIncludes('accounts')
->get();
if (request()->ajax()) {
return DataTables::of($clients)->make(true);
}
return view('client.index', compact('clients'));
}
This worked perfectly and the json response looked like so:
{data: [{id: "4428", number: "492501", name: "Test Client", email: "test#test.com",…},…]
draw:1
input:{view: "datatable", draw: "1",…}
recordsFiltered:2
recordsTotal:2}
Then I updated my index call to use my resource collection that looks like this:
public function toArray($request)
{
switch ($request->view) {
case 'datatable':
self::withoutWrapping();
return DataTables::of($this->collection)->make(true);
}
return parent::toArray($request);
}
The response is now plopped in an "original" attribute and a bunch of other items are added to the response. I don't understand why. It looks like this:
*callback: null
*charset: null
*content: <The above response is in here as a string>
*encodingOptions: 0
*statusCode: 200
*statusText: "OK"
*version: "1.0"
exception: null
headers: {}
original: <The above response is in here as an object>
I can set my dataSrc on datatables to original.data and it works fine but where did all this extra stuff come from? I have used a few other resource collections and never had all this stuff added in.
Update: because everything i am looking for is in "original" the pagination breaks as well as most of the other datatable functionality. If I move this return back into the controller it works fine.
So, the answer has to do with response type. The eloquent resource has an undocumented function called "toResponse" and if your return is going to be some kind of jsonResponse you need to modify it instead of your toArray method. What was happening was I was returning a JsonResponse and it was turning it into an array and just returning that json encoded.
To be clear as mud, here is my new Resource:
public function toResponse($request)
{
switch ($request->view) {
case 'datatable':
self::withoutWrapping();
return DataTables::of($this->collection)->toJson();
}
return parent::toResponse($request);
}
So, to reiterate, if you are returning an array or something that conforms to an array correctly (which datatables jsonresponse does not) you override "toArray". If you are returning a jsonResponse you need to override "toResponse".
Another option is to have your code start in toArray but when you know your going to return a jsonResponse you call $this->toResponse($request). Option is yours.

Best practices to define response in action controller Laravel

I have a method inside PostController
class PostController extends Controller {
public function index() {
$posts = Post::all();
return response($posts);
}
}
Two way:
class PostController extends Controller {
public function index() {
$posts = Post::all();
return $posts;
}
}
Both work fine but which way is better and more correctly?
I personnaly prefer this version:
return \Response::json($data);
Because it makes clear that the response is actual json data.
Just make sure your code is understandable by someone new on your project.
If you are writing an API project, where everything is always returned in json, simply return the model because you don't have to make the reader learn that it's JSON because everything is in JSON everywhere.
On the other hand, if it's some sort of mixed project (some routes return view, JSON, XML, whatever), try to make is as obvious as you can that this specific route return JSON data and nothing else.
Also as stated in comments, stay consistent. The shorter isn't the better. The better is the one that is simple to read and give enough info about what's going on.
It doesn't matter actually.. its depends on your desire and consistency..
return Response::json($model);
//or
return response()->json($model);
//or
return $model;
it give you same output..but if you using response, you can set the status code. most of the time, this reponse thing is used in API project.

Laravel 5 Invalid Custom Request - do not redirect

I have a custom Request Class on Laravel 5 which handles form inputs (POST). the thing is, I want to use the same request class for a GET method but instead of redirecting the user back to the original request URL (which causes an infinite) loop I want to throw an exception (if the request is not valid), how is that possible?
In your custom Request class, you can override the failedValidation method that is defined in the FormRequest class.
I.e. place this method in your Request class:
protected function failedValidation(\Illuminate\Validation\Validator $validator) {
throw new \Exception('Error processing request');
}
Overriding the response() method can also be used to return a preferred response, personally I have used this to return the errors in JSON form, all that was required to do this was to return a JsonResponse with the errors and response code:
public function response(array $errors)
{
return new JsonResponse($errors, 422);
}
You can add something like this in your request method:
if (Request::isMethod('get'))
{
//Here you can add your custom exception.
}
You can see the documentation for more info about this: http://laravel.com/docs/5.0/requests#other-request-information

Resources