I'm using Laravel 5.1 and I'm unable to use its Request injection.
If I print_r($request->all()), I get an empty array:
Array
(
[\] =>
)
But when I check Request::getContent(), it shows that I have content.
{"test": "test"}
Why is this? I have never had this problem before.
My controller method
public function state(Requests\CheckState $request) {
print_r($request->all());
print_r($request->getContent());
}
My Request
class CheckState extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
];
}
}
When sending raw JSON data to Laravel, be sure to specify Content-Type: application/json
This is because the Request class checks for JSON content this way:
/**
* Determine if the request is sending JSON.
*
* #return bool
*/
public function isJson()
{
return Str::contains($this->header('CONTENT_TYPE'), '/json');
}
If the header is omitted, the framework assumes the request is plaintext.
Related
Merry Christmass team!
I have a problem trying to figure out how to pass a method with my own constraints in a controller that is bound to request patter paradigm:
Sample Controller Code:
class SampleController
{
protected $model = SampleModel::class;
protected $indexRequest = IndexRequest::class;
}
Request Class
class IndexRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [];
}
Assume I have a method that I want to do something different.Say I want to fetch some data based on some column constraints.
Whats the approach?
I am building a web app + REST server with Laravel 5.5 so that the users can either access the services online with a web interface or indirectly use the APIs via the mobile app.
Now the objective would be to have the same controllers capable of handling both API and direct requests leveraging on Laravel built-in double routing and automatic JSON responses for FormRequests.
The main problems I am figuring are:
How to handle JSON (for API access) and HTML view (for web visitors) responses on the same controller function?
How to manage "Resource not found" errors in the controller and subsequently reply to the user in the desired way?
A possible approach to the second issue would be to use "findOrFail" and then catch the exception, looking whether the request has got an "Accpet" header and reply accordingly but it looks quite bulky.
Here is a brief overview of a controller I am working on; I haven't implemented any checks on the retrieved data yet.
class UsersController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$users = User::all();
return UserResource::collection($users);
}
/**
* Store a newly created resource in storage.
*
* #param \Washery\Http\Request\StoreUser $request
* #return \Illuminate\Http\Response
*/
public function store(StoreUser $request)
{
User::create($request->all());
return response()->json(['message' => 'success'], 200);
}
/**
* Display the specified resource.
*
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$user = User::find($id);
return new UserResource($user);
}
/**
* Update the specified resource in storage.
*
* #param \Washery\Http\Request\UpdateUser $request
* #return \Illuminate\Http\Response
*/
public function update(UpdateUser $request)
{
User::update($request->all());
return response()->json(['message' => 'success'], 200);
}
/**
* Remove the specified resource from storage.
*
* #param \Washery\User $user
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
User::find($id)->delete();
return response()->json(['message' => 'success'], 200);
}
}
An approach would be to know where the request is coming from. If it comes from the mobile (API request), then return JSON, else, return a view.
if ($request->expectsJson()) {
return response()->json(['message' => 'success']); // No need to put 200 here.
} else {
return view('view.path');
}
You can learn more about the request api here: https://laravel.com/api/5.5/Illuminate/Http/Request.html
I've been trying to add a FormRequest with rules and message to my delete method, but the request is coming back empty and the rules are failing every time.
Is it possible to get the request data in a delete method?
Here's my request class:
use App\Http\Requests\Request;
class DeleteRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'staff_id' => ['required', 'exists:users,uid'],
'reason' => ['required', 'string'],
];
}
/**
* Get custom messages for validator errors.
*
* #return array
*/
public function messages()
{
return [
'staff_id.required' => staticText('errors.staff_id.required'),
'staff_id.exists' => staticText('errors.staff_id.exists'),
'reason.required' => staticText('errors.reason.required'),
'reason.string' => staticText('errors.reason.string'),
];
}
}
And the controller:
/**
* Handle the 'code' delete request.
*
* #param integer $id The id of the code to fetch.
* #param DeleteRequest $request The request to handle the data.
* #return response
*/
public function deleteCode($id, DeleteRequest $request)
{
dd($request->all());
}
Even though the HTTP/1.1 spec does not explicitly state that DELETE requests should not have an entity body, some implementations completely ignore the body which contains your data, e.g. some versions of Jetty and Tomcat. On the other hand, some clients do not support sending it as well.
Think of it as a GET request. Have you seen any with form data? DELETE requests are almost the same.
You can read a LOT on the subject. Start here:
RESTful Alternatives to DELETE Request Body
It seems like that you want to alter the state of the resource rather than destroying it. Soft-deleting is not deleting and thus requires either a PUT or a PATCH method which both support entity bodies. If soft-deleting is not the case, you're doing two operations through one call.
I'm bulding API Laravel 5 application with RESTful controllers. I have method destroy defined this way in controller:
public function destroy($id)
{
App::abort(404);
}
because at the moment I don't want to handle it. The strange thing is when I use such code, I get 404 header but also get output from my show method:
public function show($id)
{
die('show method');
}
so when using DELETE method for my resource I get 404 code with output show method.
I'm 100% sure I'm launching destroy method, because if I put in my destroy method:
public function destroy($id)
{
die('destroy');
}
I will have displayed destroy with 200 status code
I'v tested it in PhpStorm but also with this Firefox addon and in both cases result is the same.
The question is - what is going here and how to return just 404 code without data or with empty data?
EDIT
I've investigated this issue further and what I discovered. If I run my app on localhost with:
DELETE http://lara404/test/1
I get pure 404 error as it should be.
I copied exact same code and run it in Vagrant. I run url:
DELETE http://lara404.app/test/1
and now I'm getting 404 code with abcdef message.
The only things I changed in default installation is:
1) adding at the beginning of routes.php
$router->resource('test','TestController');
2) Putting into TestController the following code:
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App;
class TestController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
dd('xxx');
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
return "abcdef";
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
App::abort(404);
}
}
3) Commenting in Kernel.php line:
'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken'
I've just checked it also with fresh installation of Laravel 5 (not using any specific commit) and exactly same happens - the same code launched on localhost works fine and the same code running on Vagrant goes to show method also
You need this if using json -
public function destroy($id)
{
return Response::json(null, 404);
}
Or this if not using json -
public function destroy($id)
{
return Response::make("", 404);
}
I get the error when trying to make a post call to /api/subject/search
I assume it's a simple syntax error I'm missing
I have my api routes defined below
Route::group(array('prefix' => 'api'), function()
{
Route::post('resource/search', 'ResourceController');
Route::resource('resource', 'ResourceController');
Route::post('subject/search', 'SubjectController');
Route::resource('subject', 'SubjectController');
Route::resource('user', 'UserController');
Route::controller('/session', 'SessionController');
Route::post('/login', array('as' => 'session', 'uses' => 'SessionController#Store'));
});
And my controller is mostly empty
class SubjectController extends \BaseController
{
public function search()
{
$subjects = [];
if((int)Input::get('grade_id') < 13 && (int)Input::get('grade_id') > 8)
$subjects = Subject::where('name', 'like', '%HS%')->get();
else
$subjects = Subject::where('name', 'not like', '%HS%')->get();
return Response::json([
'success' => true,
'subjects' => $subjects->toArray()
]);
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
You need to specify the method.
try
Route::post('subject/search', 'SubjectController#search');
See the named route example:
Laravel Docs
In your case I think search is not resolved by the controller to load the search() method. You are also sending a POST for search functionality and I guess it's better to do a GET request since POST and PUT are for storing data.
Conventions
When creating API's it's a good thing to stick to naming conventions and patterns.
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Solution
Your route could be simpler like this: api.yourdomain.com/api/subject?search=term1,term2. Doing this with a GET query makes it going to the index() method. There you can check the GET params and do your search stuff and return.
Check this for the cleanest and truely RESTful way to make an API in Laravel:
How do I create a RESTful API in Laravel to use in my BackboneJS app
I got same error when accessing object at index of an empty array in view blade php file.