Esta es la solución más completa que te podemos aportar, pero primero mírala pausadamente y valora si se adapta a tu trabajo.
Solución:
Finalmente descubrí por qué esto no funciona. No es un problema de errores en el código de implementación o Laravel, sino uno de: (i). escribir un buen código PHP para manejar el resultado evidente, lo que claramente no hice; (ii). documentación insuficiente dentro de Laravel sobre cómo usar realmente la respuesta de error de validación. Elige tu opción.
La validación de Laravel arroja un Illuminate Validation ValidationError. Lo crea o no, esto en realidad hace que el mensaje de error predeterminado sea “Los datos proporcionados no eran válidos”, por lo que cuando detecta una Exception y recupera su $ e-> getMessage (), este mensaje de error predeterminado es lo que usted (correctamente) obtener.
Lo que debe hacer es capturar el Illuminate Validation ValidationError, lo que debería haber hecho originalmente, ¡duh! – y luego use sus métodos para ayudarlo a extraer los mensajes de error.
Aquí está la solución que se me ocurrió:
validate(
$arrValid,
array(
'name.required' => 'Name is missing',
'name.alpha_num' => 'Name must be alphanumeric',
'user_id.required' => 'User Id is missing',
'user_id.integer' => 'User Id must be an integer',
)
);
catch (IlluminateValidationValidationException $e )
/**
* Validation failed
* Tell the end-user why
*/
$arrError = $e->errors(); // Useful method - thank you Laravel
/**
* Compile a string of error-messages
*/
foreach ($arrValid as $key=>$value )
$arrImplode[] = implode( ', ', $arrError[$key] );
$message = implode(', ', $arrImplode);
/**
* Populate the respose array for the JSON
*/
$arrResponse = array(
'result' => 0,
'reason' => $message,
'data' => array(),
'statusCode' => $e->status,
);
catch (Exception $ex)
$arrResponse = array(
'result' => 0,
'reason' => $ex->getMessage(),
'data' => array(),
'statusCode' => 404
);
finally
return response()->json($arrResponse);
Entonces, de hecho, Laravel estaba proporcionando la respuesta correcta e hizo lo que decía en el costado de la lata, pero no lo estaba aplicando correctamente. Independientemente, como una ayuda para mi futuro y otros marineros PHP perdidos en Laravel-sea, proporciono la solución.
Además, gracias a Marcin por señalar mi codificación defectuosa, que habría causado un problema incluso si hubiera implementado la solución anterior.
El problema es probablemente que el controlador de excepciones predeterminado de Laravel no está preparado para transmitir información de validación detallada al usuario. En cambio, oculta los detalles de la excepción al usuario, lo que normalmente es lo correcto porque puede representar un riesgo de seguridad para otras excepciones además de las de validación.
En otras palabras; si el controlador de excepciones render
función (implementada en /app/Exceptions/Handler.php
) detecta sus errores de validación, se interpretarán como una excepción general de la aplicación y el mensaje de error general enviado al usuario siempre leerá ‘Los datos proporcionados no eran válidos’.
Asegúrate que render
El método ignora instancias de IlluminateValidationValidationException
, y debería obtener la respuesta que espera:
public function render($request, Exception $exception)
if (! $exception instanceof IlluminateValidationValidationException))
// ... render code for other Exceptions here
Otra forma de hacer que el controlador de excepciones retransmita los detalles de la excepción ValidationException con la respuesta sería hacer algo como esto en el render
método:
if ($exception instanceof ValidationException && $request->expectsJson())
return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
Fondo
Laravel está básicamente (ab) usando Excepciones aquí. Normalmente, una excepción indica un problema (en tiempo de ejecución) en el código, pero Laravel los usa como un mecanismo para facilitar la validación de solicitudes y proporcionar comentarios al usuario. Es por eso que, en este caso, sería incorrecto dejar que su controlador de excepciones maneje la excepción; no es una excepción de aplicación, es información destinada al usuario.
El código en la respuesta proporcionada por OP funciona, porque él mismo detecta la ValidationException, evitando que sea detectada por el controlador de excepciones de la aplicación. No hay ningún escenario en el que creo que sería deseable, ya que es una mezcla clara de preocupaciones y genera un código horriblemente largo e ilegible. Simplemente ignorar las ValidationExceptions o tratarlas de manera diferente en el Exception Handler como mostré anteriormente debería funcionar bien.
Acabo de ver esto, pero todo lo que necesita hacer es mover la llamada de validación antes de el intento / captura
$p_oRequest->validate(
[
'name' => 'required|alpha_num',
'user_id' => 'required|integer',
],
[
'name.required' => 'Name is required',
'name.string' => 'Name must be alphanumeric',
'user_id.required' => 'Curator User Id is required',
'user_id.required' => 'Curator User Id must be an integer',
]
);
try
...
catch(Exception $e)
return back()->withErrors($e->getMessage())->withInput();
Debido a que Laravel detecta la excepción de validación automáticamente y lo devuelve con la entrada anterior y una array de errores que puede generar como
@if ($errors->any())
@foreach ($errors->all() as $error)
- $error
@endforeach
@endif
Comentarios y valoraciones de la guía
Si eres capaz, tienes el poder dejar un artículo acerca de qué le añadirías a esta división.