it-swarm.com.de

Bei fehlgeschlagener Überprüfung wird eine Standardfehlermeldung zurückgegeben, obwohl benutzerdefinierte Meldungen angegeben wurden

Ich bekomme nicht die Antwort, die ich erwarte.

Dies ist der Controller-Code für eine Standort-Webdienst-Anfrage:

<?php
namespace App\Http\Controllers;

use App\Location;
use Illuminate\Http\Request;


class LocationController extends Controller
{


    /**
     * Action method to add a location with the supplied Data
     * 
     * @param \Illuminate\Http\Request $p_oRequest Request
     * 
     * @return JSON
     */
    public function add(Request $p_oRequest)
    {

        try {

            $p_oRequest->validate(
                array(
                    'name' => 'required|alpha_num',
                    'user_id' => 'required|integer',
                ),
                array(
                    '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',
                )
            );

        } catch (\Exception $ex) {

            $arrResponse = array(
                'result' => 0,
                'reason' => $ex->getMessage(),
                'data' => array(),
                'statusCode' => 404
            );

        } finally {

            return response()->json($arrResponse);

        }

    }

}

Die Anfrage lautet http: //mydomain/index.php/api/v1/location/add? Name = @ ! ^

Der erwartete Antwortgrund ist: {"Ergebnis": 0, "Grund": "Name muss alphanumerisch sein", "Daten": [], "Statuscode": 404}

Die tatsächliche Antwort lautet stattdessen: {"Ergebnis": 0, "Grund": "Die angegebenen Daten waren ungültig.", "Daten": [], "Statuscode": 404}

Bitte helfen Sie. Das nervt mich.

3
user3125602

Das Problem ist wahrscheinlich, dass der Standard-Ausnahmehandler von Laravel nicht bereit ist, detaillierte Validierungsinformationen an den Benutzer weiterzuleiten. Stattdessen werden Ausnahmedetails vor dem Benutzer ausgeblendet. Dies ist normalerweise die richtige Vorgehensweise, da dies ein Sicherheitsrisiko für andere Ausnahmen als die Validierungsausnahmen darstellen kann.

Mit anderen Worten; Wenn die in /app/Exceptions/Handler.php implementierte Funktion render des Ausnahmebehandlungsprogramms Ihre Überprüfungsfehler abfängt, werden diese als allgemeine Anwendungsausnahme interpretiert und die allgemeine Fehlermeldung, die an den Benutzer weitergeleitet wird, lautet immer "Die angegebenen Daten waren ungültig".

Stellen Sie sicher, dass die Methode render\Illuminate\Validation\ValidationException ignoriert und Sie die erwartete Antwort erhalten:

public function render($request, Exception $exception) {

    if (! $exception instanceof \Illuminate\Validation\ValidationException)) {

        // ... render code for other Exceptions here

    }

}

Eine andere Möglichkeit, die Exception-Handler-Relay-ValidationException-Details mit der Antwort zu versehen, besteht darin, in der render-Methode Folgendes zu tun:

if ($exception instanceof ValidationException && $request->expectsJson()) {
    return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
}

Hintergrund

Laravel verwendet hier grundsätzlich (ab) Exceptions. Normalerweise weist eine Ausnahme auf ein (Laufzeit-) Problem im Code hin, doch Laravel verwendet sie als Mechanismus, um die Validierung von Anforderungen zu vereinfachen und dem Benutzer Feedback zu geben. Aus diesem Grund wäre es in diesem Fall falsch, Ihren Ausnahmehandler die Ausnahme behandeln zu lassen - es handelt sich nicht um eine Anwendungsausnahme, sondern um Informationen, die für den Benutzer bestimmt sind.

Der Code in der Antwort von OP funktioniert, da er die ValidationException selbst abfängt und verhindert, dass sie vom Exception Handler der Anwendung abgefangen wird. Es gibt kein Szenario, in dem ich das für wünschenswert halte, da es eine klare Mischung von Bedenken darstellt und für schrecklich langen und unlesbaren Code sorgt. Wenn Sie ValidationExceptions einfach ignorieren oder im Exception Handler wie oben gezeigt anders behandeln, ist das kein Problem.

3
Wilbo Baggins

Ich habe endlich herausgefunden, warum das nicht funktioniert. Es handelt sich nicht um Fehler im Implementierungscode oder in Laravel, sondern um eine der folgenden Ursachen:. guten PHP Code schreiben, um mit dem offensichtlichen Ergebnis fertig zu werden, was ich natürlich nicht getan habe; (ii). Unzureichende Dokumentation in Laravel zur tatsächlichen Verwendung der Validierungsfehlerantwort. Treffen Sie Ihre Wahl.

Laravels Validierung löst einen Illuminate\Validation\ValidationError aus. Ob Sie es glauben oder nicht, hierdurch wird die Fehlermeldung standardmäßig auf "Die angegebenen Daten waren ungültig." Gesetzt. Wenn Sie also eine\Exception abfangen und deren $ e-> getMessage () abrufen, entspricht diese Standardfehlermeldung Ihrer (korrekten) Vorgehensweise. erhalten.

Was Sie tun müssen, ist das Erfassen des\Illuminate\Validation\ValidationError - was ich ursprünglich hätte tun sollen, duh! - und verwenden Sie dann seine Methoden, um die Fehlermeldungen daraus zu destillieren.

Hier ist die Lösung, die ich mir ausgedacht habe:

<?php
namespace App\Http\Controllers;

use App\Location;
use Illuminate\Http\Request;


class LocationController extends Controller
{

    /**
     * Action method to add a location with the supplied Data
     * 
     * @param \Illuminate\Http\Request $p_oRequest Request
     * 
     * @return JSON
     */
    public function add(Request $p_oRequest)
    {
        try {

            $arrValid = array(
                'name' => 'required|alpha_num',
                'user_id' => 'required|integer',
            );
            $p_oRequest->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 (\Illuminate\Validate\ValidationException $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);

        }

    }

}

Tatsächlich lieferte Laravel die richtige Antwort und tat, was auf der Seite der Dose stand, aber ich habe es nicht richtig angewendet. Unabhängig davon biete ich als Hilfe für die Zukunft von mir und anderen verlorenen PHP-Seefahrern auf Laravel-Sea die Lösung an.

Außerdem danke ich Marcin für den Hinweis auf meine fehlerhafte Codierung, die selbst dann ein Problem verursacht hätte, wenn ich die oben genannte Lösung implementiert hätte.

2
user3125602

Ihre Nachrichten sollten Validierungsregeln sein, anstatt:

'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',

du solltest haben:

'name.required' => 'Name is required',
'name.alpha_num' => 'Name must be alphanumeric',
'user_id.required' => 'Curator User Id is required',
'user_id.integer' => 'Curator User Id must be an integer',
1

Ich habe das gerade erst gesehen, aber alles, was Sie tun müssen, ist den Validate-Aufruf vor dem try/catch zu verschieben

$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();
}

Weil Laravel die Validierungsausnahme automatisch abfängt und Sie mit alten Eingaben und einer Reihe von Fehlern zurückgibt, die Sie wie folgt ausgeben können

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
0
justrusty