Wie kann ich einen Validierungsfehler / eine Validierungsausnahme in Laravel manuell zurückgeben oder auslösen?

75

Haben Sie eine Methode, die CSV-Daten in eine Datenbank importiert. Ich mache eine grundlegende Validierung mit

class CsvImportController extends Controller
{
    public function import(Request $request)
    {   
        $this->validate($request, [
            'csv_file' => 'required|mimes:csv,txt',
        ]);

Aber danach können Dinge aus komplexeren Gründen schief gehen, weiter unten im Kaninchenbau, was zu Ausnahmen führt. Ich kann hier kein richtiges Validierungsmaterial für die validateMethode schreiben , aber ich mag es wirklich, wie Laravel funktioniert, wenn die Validierung fehlschlägt und wie einfach es ist, die Fehler in die Blade-Ansicht usw. einzubetten, also ...

Gibt es eine (vorzugsweise saubere) Möglichkeit , Laravel manuell mitzuteilen, dass "Ich weiß, dass ich Ihre validateMethode gerade nicht angewendet habe, aber ich möchte wirklich, dass Sie diesen Fehler hier aufdecken, als ob ich es getan hätte"? Gibt es etwas, das ich zurückgeben kann, eine Ausnahme, mit der ich Dinge einpacken kann, oder etwas?

try
{
    // Call the rabbit hole of an import method
}
catch(\Exception $e)
{
    // Can I return/throw something that to Laravel looks 
    // like a validation error and acts accordingly here?
}
Svish
quelle
Was ist mit der Erweiterung der Validierung von Laravel, um Ihre komplexe Behandlung wie diese Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; });hinzuzufügen ? Dann können Sie die Foo-Regel in die Regeln aufnehmen 'csv_file' => 'required|foo|mimes:csv,txt',?
Maraboc
@Svish Haben Sie Ihre benutzerdefinierte Validierungsklasse, um einen Validierungsfehler auszulösen?
Ako
1
@Svish Ich denke, Madalinivascus Lösung ist Ihre Antwort.
Ako
1
Sie können die Fehlermeldung im catch-Block abfangen und Ihre Arbeit erledigen. sotry { //my stuff } catch (Exception $ex) { echo $ex->getMessage(); //Message //$ex->getFile(); //File //$ex->getLine(); //Line }
Raunak Gupta
1
oder Sie können auch eine benutzerdefinierte Validierung durchführen und den Fehler try { $validator = Validator::make($request, ['csv_file' => 'required|mimes:csv,txt']); if ($validator->fails()) { throw new Exception(implode('<br>', $validator->errors()->all()), 999); } } catch (Exception $ex) { if ($ex->getCode() == 999) { //this is a custom error } echo $ex->getMessage(); //Message }
auslösen

Antworten:

169

Ab Laravel 5.5 verfügt die ValidationExceptionKlasse über eine statische MethodewithMessages , die Sie verwenden können:

$error = \Illuminate\Validation\ValidationException::withMessages([
   'field_name_1' => ['Validation Message #1'],
   'field_name_2' => ['Validation Message #2'],
]);
throw $error;

Ich habe das nicht getestet, aber es sollte funktionieren.

Aktualisieren

Die Nachricht muss nicht in ein Array eingeschlossen werden. Sie können auch tun:

use Illuminate\Validation\ValidationException;

throw ValidationException::withMessages(['field_name' => 'This value is incorrect']);
Erin
quelle
2
Ah! Das hat funktioniert und auch die "Notwendigkeit" einer Hilfsmethode zum Entfernen des hässlichen Messagebag-Materials beseitigt. 😛 Danke!
Svish
3
Es ist so ein Almos, anstatt ein einfaches Array zu sein, es ist ein multidimentionales Array, dieses funktioniert $error = ValidationException::withMessages([ "one_thing" => ["Validation Message #1"], "another_thing" => ['Validation Message #2'] ]);
Jose Palazuelos
@JosePalazuelos Da Laravel> v5.5 das Nachrichtenargument mit Arr :: wrap ($ value) in ein Array umwandelt, ist es nicht erforderlich, das 2D-Array zu übergeben, es funktioniert mit einem einfachen Schlüsselwert-Array. Siehe github.com/laravel/framework/blob/5.5/src/Illuminate/Validation/…
ivanhoe
Funktioniert wie ein Zauber auf 6.6. Der einzige Nachteil ist, wie andere Validierungsfehlermeldungen verhindert werden.
IGP
Vielen Dank! Genau das, wonach ich gesucht habe.
Sylar
22

Laravel <= 6.2 Diese Lösung hat bei mir funktioniert:

$validator = Validator::make([], []); // Empty data and rules fields
$validator->errors()->add('fieldName', 'This is the error message');
throw new ValidationException($validator);
Mārtiņš Briedis
quelle
11

Einfach vom Controller zurückkehren:

return back()->withErrors('your error message');
Mantas D.
quelle
1
Diese Methode funktioniert, aber da ich zurückgegangen bin (), zeigt das Formular keine vorherigen Werte mit {{old ('fieldname')}} an
Chris
5
füge withInput () hinzu, so return back () -> withErrors ('error') -> withInput ();
Mantas D
1
Beste Antwort (nicht vergessenwithInput()
Vahid Amiri
4

Sie können eine benutzerdefinierte Nachrichtentasche ausprobieren

try
{
    // Call the rabbit hole of an import method
}
catch(\Exception $e)
{
    return redirect()->to('dashboard')->withErrors(new \Illuminate\Support\MessageBag(['catch_exception'=>$e->getMessage()]));
}
madalinivascu
quelle
Das hat fast funktioniert. Das MessageBagscheint keine Ausnahmen zu mögen? Das Aufrufen mit new MessageBag(['exception' => $e])führt zu einem leeren Fehlersatz, während new MessageBag(['exception' => $e->getMessage()])dies nicht der Fall ist ... 🤔
Svish
Sie müssen $ e in Text konvertieren oder eine benutzerdefinierte Nachricht verwenden
madalinivascu
2

Für Laravel 5.8:

.

Der einfachste Weg, eine Ausnahme auszulösen, ist folgender:

throw new \ErrorException('Error found');
Syamsoul Azrien
quelle