Estoy usando FormularioSolicitud para validar desde el cual se envía en una llamada API desde la aplicación de mi teléfono inteligente. Entonces, quiero que FormRequest siempre devuelva json cuando falle la validación.
Vi el siguiente código fuente del marco de Laravel, el comportamiento predeterminado de FormRequest es devolver json si el reqeust es Ajax o wantJson.
//IlluminateFoundationHttpFormRequest class
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
* @return SymfonyComponentHttpFoundationResponse
*/
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 mediante el soporte json de forma predeterminada sin configurar ningún encabezado. Entonces, traté de encontrar algunas opciones para forzar la respuesta json de FormRequest en IlluminateFoundationHttpFormRequest
clase. Pero no encontré ninguna opción que sea compatible de forma predeterminada.
Solución 1: Clase abstracta de solicitud de sobrescritura
Traté de sobrescribir la clase abstracta de solicitud de mi aplicación como sigue:
<?php
namespace Laravel5CgHttpRequests;
use IlluminateFoundationHttpFormRequest;
use IlluminateHttpJsonResponse;
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 SymfonyComponentHttpFoundationResponse
*/
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);
}
}
yo añadí protected $forceJsonResponse = false;
para establecer si necesitamos forzar la respuesta json o no. Y, en cada FormRequest que se extiende desde la clase abstracta Request. Yo configuro esa opción.
Por ejemplo: hice un StoreBlogPostRequest y configuré $forceJsoResponse=true
para este FormRequest y haz que responda json.
<?php
namespace Laravel5CgHttpRequests;
use Laravel5CgHttpRequestsRequest;
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: Agregue un Middleware y fuerce el encabezado de solicitud de cambio
Construyo un middleware como los siguientes:
namespace Laravel5CgHttpMiddleware;
use Closure;
use SymfonyComponentHttpFoundationHeaderBag;
class AddJsonAcceptHeader
{
/**
* Add Json HTTP_ACCEPT header for an incoming request.
*
* @param IlluminateHttpRequest $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 estas soluciones son buenas. ¿Y hay alguna forma Laravel de ayudarme en esta situación?
Hola, solo como una sugerencia, ya que está solicitando un tipo de respuesta predeterminado, entonces, ¿por qué no simplemente agregando un middleware y agregando el tipo de solicitud a json en su método de manejo?
$request->header('accept', 'application/json'); return $next($request);
con estos, tiene un lugar para hacer una mayor expansión, sin anular siempre ningún método– terry bajo
20 jul.
Gracias ! Es una buena idea. Creo. Actualizaré esta implementación en la pregunta anterior.
– Chung
20 jul.
Lo siento. Traté de configurar $request->header(‘Accept’,’application/json’); en un middleware, pero descubrí que mi solicitud tiene el encabezado Aceptar predeterminado ‘/‘, por lo que no pude sobrescribir ese encabezado Aceptar. No puse nada en mi solicitud.
– Chung
20 jul.
no importa, ya sea que tenga el valor de aceptación predeterminado establecido en su encabezado, el valor del middleware lo anulará
$request = $request->header('Accept','application/json'); return $next($request);
Estoy pensando en eso, la solicitud no se mantiene.– terry bajo
20 jul.
Encontré la forma de sobrescribir el encabezado de la solicitud. Necesitamos configurar $request->server y reconstruir headerBag de la siguiente manera: $request->server->set(‘HTTP_ACCEPT’, ‘application/json’); $solicitud->encabezados = new HeaderBag($solicitud->servidor->getHeaders());
– Chung
21 jul.