43

I am trying to make a post request of json to Laravel. The request is received on the server however when I try to access a property I get: "Trying to get property of non-object". On the client I'm using angularjs.

angular:

$http.post($rootScope.globals.basePath+"login/handleAjax",{"id" : obj.values[0].id,"profileUrl" : obj.values[0].publicProfileUrl}).success(function(data){
             console.log("got success!",data);
         });

laravel:

class LoginController extends BaseController {
/*User logs in to linkedin and sends his id through ajax to this function*/
public function handle_ajax() {
    $data = Input::all();
    *//Clockwork is just a debugging extension I'm using*
    Clockwork::info($data->id); **//"Trying to get property of non-object".**
}

Note: I can see in Fiddler that the JSON being sent is valid and that it reaches the controller+method (http 200).

The post request itself (As seen with Fiddler)

Headers: 
Accept: application/json, text/plain, */*
...
Text View:
{"id":"my id","profileUrl":"http://www.linkedin.com/pub/yoel-blum/51/373/76"}
Joel Blum
  • 7,750
  • 10
  • 41
  • 60
  • 3
    Isn't it `Input::json()->all()` ? – Connor Tumbleson Jan 19 '14 at 16:46
  • 1
    Laravel does not know you've posted JSON. You'll have to `json_decode` it yourself or use `Input::json()->all()` that is not documented yet, although in the sources (https://github.com/laravel/framework/blob/master/src/Illuminate/Http/Request.php#L429). – Sergiu Paraschiv Jan 19 '14 at 16:48
  • Doesn't seem to solve it : $data = Input::json()->all(); return $data->id; and I get the same error ... – Joel Blum Jan 19 '14 at 16:52

3 Answers3

69

Update: Laravel 5

Please note as of Laravel 5.0, the Input facade has been removed from the official documentation (and in 5.2 it was also removed from the list of default Facades provided) in favor of directly using the Request class that Input invokes, which is Illuminate\Http\Request.

Also, as of the Laravel 5.1 documentation, all references to the Request facade have been removed, again in preference of using the Illuminate\Http\Request instance directly, which it encourages you to do via dependency injection in either:

...your Controller Method:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function update(Request $request, $id)
    {
        $data = $request->json()->all();
    }
}

...or a Route Closure (as of 5.3):

use Illuminate\Http\Request;

Route::get('/', function (Request $request) {
    $data = $request->json()->all();
});

json() and ParameterBag

It's worth noting that $request->json() returns an instance of Symfony\Component\HttpFoundation\ParameterBag, and that ParameterBag's ->all() method returns an associative array, and not an object as the OP expected.

So one would now fetch the rough equivalent of $_POST['id'] as follows:

$data = $request->json()->all();
$id = $data['id'];

`Input` and `Request` facades: Current Status

Both facades have been removed from the official documentation (as of 5.1), and yet they both also remain in the source code with no 'deprecated' label.

As mentioned earlier, Input was removed as a default facade ('alias') in 5.2, but as of 5.4, the Request facade remains a default.

This seems to imply that one could still use the Request facade to invoke methods on the Request instance (e.g. Request::json()), but that using dependency injection is simply now the officially preferred method.

jdunk
  • 2,738
  • 2
  • 17
  • 25
  • Any idea how to retrieve an stdClass object from that `ParameterBag `, not array? – Greendrake Jan 29 '16 at 02:54
  • 3
    @DrakeES You'll need to just cast it as an object: `(object) Request::json()->all()` since `ParameterBag`'s params are stored internally as an associative array, and at present there is no "return as object" option. See also this question: http://stackoverflow.com/questions/19272011/how-to-convert-an-array-into-an-object-using-stdclass – jdunk Feb 29 '16 at 16:50
  • @Greendrake See [this thread](https://github.com/laravel/framework/issues/443) for an interesting historical discussion on exactly this, including a comment from T.O. himself (which looks familiar, haha). – jdunk Feb 11 '17 at 02:34
  • @jdunk can I send few parameters in the post and few in the json? – Anto S Mar 12 '19 at 13:30
12

NOTE: this answer is only applicable for old Laravel versions (4.2 and earlier)!

Laravel's Input::all method returns an associative array, not an object of PHP's stdClass.

$data = Input::all();
$data['id']; // The ID of the request
rob74
  • 4,939
  • 29
  • 31
Jacob Budin
  • 9,753
  • 4
  • 32
  • 35
8

To expand (and correct) the above, in Laravel 5 you would retrieve JSON as shown:

public function handle_ajax(Request $request) {
    $data = (object) $request->json()->all();
    Clockwork::info($data->id);
}

In non-trivial examples you might want to also validate your input first.

Pete Thorne
  • 2,656
  • 4
  • 21
  • 29
  • 1
    Thanks for [indirectly] bringing this to my attention @Pete. My answer at the time was correct for Laravel 5.0, but it was indeed later (when 5.1+ came out) then somewhat inaccurate to have said just "in Laravel 5, what you want is Request::json->all()" -- even though that actually still totally works -- because it was removed from the documentation (although not the source code) in favor of what you noted here. I updated my answer accordingly. – jdunk Feb 11 '17 at 02:07