2016-02-11 13 views
10

buduję REST API z laravel 5.Jak zwrócić błędy AJAX ze sterownika Laravel?

W laravel 5 można podklasy App\Http\Requests\Request zdefiniowanie reguł sprawdzania poprawności, które muszą być spełnione, zanim zostaną przetworzone danej trasie. Na przykład:

<?php 

namespace App\Http\Requests; 

use App\Http\Requests\Request; 

class BookStoreRequest extends Request { 

    public function authorize() { 
     return true; 
    } 

    public function rules() { 
     return [ 
      'title' => 'required', 
      'author_id' => 'required' 
     ]; 
    } 
} 

Jeśli klient ładuje odpowiednią drogę poprzez żądanie AJAX i BookStoreRequest stwierdzi, że wniosek nie spełnia reguł, to automagicznie zwróci błąd (y) jako obiekt JSON. Na przykład:

{ 
    "title": [ 
    "The title field is required." 
    ] 
} 

Jednak metoda Request::rules() może jedynie potwierdzić wejściowego, a nawet jeśli wejście jest ważne, inne rodzaje błędów mogą pojawić się po wniosek został już zaakceptowany i przekazany do sterownika. Na przykład, powiedzmy, że kontroler musi napisać nowe informacje książkę do pliku z jakiegoś powodu-ale plik nie może zostać otwarty:

<?php 

namespace App\Http\Controllers; 

use Illuminate\Http\Request; 

use App\Http\Requests; 
use App\Http\Controllers\Controller; 

use App\Http\Requests\BookCreateRequest; 

class BookController extends Controller { 

    public function store(BookStoreRequest $request) { 

     $file = fopen('/path/to/some/file.txt', 'a'); 

     // test to make sure we got a good file handle 
     if (false === $file) { 
      // HOW CAN I RETURN AN ERROR FROM HERE? 
     } 

     fwrite($file, 'book info goes here'); 
     fclose($file); 

     // inform the browser of success 
     return response()->json(true); 

    } 

} 

Oczywiście, mogłem tylko die(), ale to bardzo brzydkie. Wolałbym, aby mój komunikat o błędzie był wyświetlany w tym samym formacie, co błędy sprawdzania poprawności. W ten sposób:

{ 
    "myErrorKey": [ 
    "A filesystem error occurred on the server. Please contact your administrator." 
    ] 
} 

Mogłabym zbudować własny obiekt JSON i go zwrócić, ale na pewno Laravel wspiera to natywnie.

Jaki jest najlepszy/najczystszy sposób to zrobić? Czy istnieje lepszy sposób na zwrócenie błędów Runtime (w przeciwieństwie do sprawdzania poprawności) z Laravel REST API?

+0

Dlaczego nie możesz po prostu wykonać 'return response() -> json (['error' => 'Your custom message']);'? –

+0

Możesz zbudować niestandardową klasę odpowiedzi json – Digitlimit

+0

'return response() -> json()' zwróci ją z 200 OK. Chcę użyć odpowiedniego kodu odpowiedzi innego niż 200 (np. 500 Błąd wewnętrznego serwera). Tak, mógłbym też to zaszyfrować - po prostu założyłem, że Laravel zapewnia już wbudowany, bardziej uporządkowany sposób robienia tego. Może to błędne założenie. – greenie2600

Odpowiedz

13

Można ustawić kod stanu w odpowiedzi json, jak poniżej:

return Response::json(['error' => 'Error msg'], 404); // Status code here 

Albo po prostu przy użyciu funkcji pomocnika:

return response()->json(['error' => 'Error msg'], 404); // Status code here 
+0

użyć funkcji response(), nie $ response() –

3

Można to zrobić na wiele sposobów.

Po pierwsze, można użyć prostego response()->json() dostarczając kod stanu:

return response()->json(/** response **/, 401); 

lub w bardziej complexe sposób, aby zapewnić, że każdy błąd jest odpowiedzią JSON, można skonfigurować funkcję obsługi wyjątku złap specjalny wyjątek i zwróć json.

Otwarte App\Exceptions\Handler i wykonaj następujące czynności:

class Handler extends ExceptionHandler 
{ 
    /** 
    * A list of the exception types that should not be reported. 
    * 
    * @var array 
    */ 
    protected $dontReport = [ 
     HttpException::class, 
     HttpResponseException::class, 
     ModelNotFoundException::class, 
     NotFoundHttpException::class, 
     // Don't report MyCustomException, it's only for returning son errors. 
     MyCustomException::class 
    ]; 

    public function render($request, Exception $e) 
    { 
     // This is a generic response. You can the check the logs for the exceptions 
     $code = 500; 
     $data = [ 
      "error" => "We couldn't hadle this request. Please contact support." 
     ]; 

     if($e instanceof MyCustomException) { 
      $code = $e->getStatusCode(); 
      $data = $e->getData(); 
     } 

     return response()->json($data, $code); 
    } 
} 

ta zwróci json żadnego wyjątku rzucony w aplikacji. Teraz tworzymy MyCustomException, na przykład w aplikacji/wyjątki:

class MyCustomException extends Exception { 

    protected $data; 
    protected $code; 

    public static function error($data, $code = 500) 
    { 
     $e = new self; 
     $e->setData($data); 
     $e->setStatusCode($code); 

     throw $e; 
    } 

    public function setStatusCode($code) 
    { 
     $this->code = $code; 
    } 

    public function setData($data) 
    { 
     $this->data = $data; 
    } 


    public function getStatusCode() 
    { 
     return $this->code; 
    } 

    public function getData() 
    { 
     return $this->data; 
    } 
} 

Możemy teraz wystarczy użyć MyCustomException lub jakiegokolwiek wyjątku rozciągający MyCustomException zwraca błąd JSON.

public function store(BookStoreRequest $request) { 

    $file = fopen('/path/to/some/file.txt', 'a'); 

    // test to make sure we got a good file handle 
    if (false === $file) { 
     MyCustomException::error(['error' => 'could not open the file, check permissions.'], 403); 

    } 

    fwrite($file, 'book info goes here'); 
    fclose($file); 

    // inform the browser of success 
    return response()->json(true); 

} 

Teraz nie tylko wyjątki rzucane przez MyCustomException zwróci błąd json, ale każdy inny wyjątek rzucony w ogóle.

Powiązane problemy