php - float - ¿Cómo forzar el retorno de FormRequest json en Laravel 5.1?
laravel validation regex (3)
Estoy usando FormRequest para validar desde que se envía en una llamada a la API desde la aplicación de mi teléfono inteligente. Por lo tanto, quiero que FormRequest siempre devuelva json cuando la validación falla.
Vi el siguiente código fuente de Laravel Framework, el comportamiento predeterminado de FormRequest es return json si reqeust es Ajax o wantJson.
//Illuminate/Foundation/Http/FormRequest class
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
* @return /Symfony/Component/HttpFoundation/Response
*/
public function response(array $errors)
{
if ($this->ajax() || $this->wantsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
Sabía que puedo agregar Accept= application/json
en el encabezado de la solicitud. FormRequest devolverá json. Pero quiero proporcionar una forma más fácil de solicitar mi API al admitir json en forma predeterminada sin configurar ningún encabezado. Entonces, traté de encontrar algunas opciones para forzar la respuesta de FormRequest json en la clase Illuminate/Foundation/Http/FormRequest
. Pero no encontré ninguna opción que esté soportada por defecto.
Solución 1: Sobrescribir la clase abstracta de solicitud
Intenté sobrescribir mi solicitud de solicitud de clase abstracta como los siguientes:
<?php
namespace Laravel5Cg/Http/Requests;
use Illuminate/Foundation/Http/FormRequest;
use Illuminate/Http/JsonResponse;
abstract class Request extends FormRequest
{
/**
* Force response json type when validation fails
* @var bool
*/
protected $forceJsonResponse = false;
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
* @return /Symfony/Component/HttpFoundation/Response
*/
public function response(array $errors)
{
if ($this->forceJsonResponse || $this->ajax() || $this->wantsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
}
protected $forceJsonResponse = false;
Para establecer si tenemos que forzar la respuesta json o no. Y, en cada solicitud de formulario que se extiende desde la clase abstracta de solicitud. Establecí esa opción.
Por ejemplo: hice un StoreBlogPostRequest y configuré $forceJsoResponse=true
para este FormRequest y le hago respuesta json.
<?php
namespace Laravel5Cg/Http/Requests;
use Laravel5Cg/Http/Requests/Request;
class StoreBlogPostRequest extends Request
{
/**
* Force response json type when validation fails
* @var bool
*/
protected $forceJsonResponse = true;
/**
* 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 [
''title'' => ''required|unique:posts|max:255'',
''body'' => ''required'',
];
}
}
Solución 2: Agregar un middleware y forzar el encabezado de solicitud de cambio
Construyo un middleware como los siguientes:
namespace Laravel5Cg/Http/Middleware;
use Closure;
use Symfony/Component/HttpFoundation/HeaderBag;
class AddJsonAcceptHeader
{
/**
* Add Json HTTP_ACCEPT header for an incoming request.
*
* @param /Illuminate/Http/Request $request
* @param /Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$request->server->set(''HTTP_ACCEPT'', ''application/json'');
$request->headers = new HeaderBag($request->server->getHeaders());
return $next($request);
}
}
Es trabajo. Pero me pregunto si esta solución es buena? ¿Y hay alguna manera Laravel para ayudarme en esta situación?
Me sorprende que esto sea tan difícil de hacer en Laravel. Al final, basado en su idea de anular la clase de Solicitud, se me ocurrió esto.
app/Http/Requests/ApiRequest.php
<?php
namespace App/Http/Requests;
class ApiRequest extends Request
{
public function wantsJson()
{
return true;
}
}
Luego, en cada controlador simplemente pase /App/Http/Requests/ApiRequest
public function index(ApiRequest $request)
Sé que este post es el rey de antaño, pero acabo de hacer un Middleware que reemplaza el encabezado "Aceptar" de la solicitud por "application / json". Esto hace que la función wantsJson()
vuelva true
cuando se usa. (Este fue el tester en Laravel 5.2 pero creo que funciona igual en 5.1)
Así es como implementas eso:
Crea la
app/Http/Middleware/Jsonify.php
archivoapp/Http/Middleware/Jsonify.php
namespace App/Http/Middleware; use Closure; class Jsonify { /** * Change the Request headers to accept "application/json" first * in order to make the wantsJson() function return true * * @param /Illuminate/Http/Request $request * @param /Closure $next * * @return mixed */ public function handle($request, Closure $next) { $request->headers->set(''Accept'', ''application/json''); return $next($request); } }
Agregue el middleware a su tabla
$routeMiddleware
de suapp/Http/Kernel.php
protected $routeMiddleware = [ ''auth'' => /App/Http/Middleware/Authenticate::class, ''guest'' => /App/Http/Middleware/RedirectIfAuthenticated::class, ''jsonify'' => /App/Http/Middleware/Jsonify::class ];
Finalmente,
routes.php
en suroutes.php
como lo haría con cualquier middleware. En mi caso se parece a esto:Route::group([''prefix'' => ''api/v1'', ''middleware'' => [''jsonify'']], function() { // Routes });