Рубрики
Uncategorized

Laravel возвращает код ошибки унифицированного формата

Автор оригинала: David Wong.

фон

Недавно я учился разрабатывать проект для Android. Проект внутреннего интерфейса начал новый проект с фреймворком PHP yii2.0, а затем перешел на laravel 5.5. Недавно я увидел, что laravel обновил новую версию, поэтому я обновил проект до laravel 6.4 В процессе использования Yii и laravel, обе платформы очень дружелюбны к веб-API и поддерживают restful в разной степени, но они все еще сталкиваются с некоторыми проблемами. Давайте возьмем laravel 6.4 в качестве примера, чтобы кратко описать проблемы, с которыми я столкнулся.

Вопрос 1. код страницы возврата поставщика

Наиболее типичным из них является laravel new. После прямого доступа браузера к локальному хосту он войдет на страницу приветствия по умолчанию шаблона laravel framework. Здесь нет большой проблемы. Проблема в том, что вы используете postman для использования этого адреса в качестве вызова интерфейса, возвращаемый код-это код страницы. То, что вы называете в конце Android, – это код страницы. Фактически, вы не будете вызывать/следовать интерфейсу при вызове интерфейса, но некоторые другие ошибки, такие как 4xx и 5xx, вернут HTML-код. Android может судить об успехе или неудаче запроса только по коду состояния, и получить информацию об ошибке очень сложно. На самом деле, мы можем добавить заголовок в Android, но… Итак, мы проверили онлайн, как с этим справиться Первый способ решить отладку postman-установить заголовки x-requested-with: XMLHttpRequest в запросе postman для имитации запроса Ajax Второй способ-заставить проект вернуться только в формат JSON и создать новое промежуточное программное обеспечение

namespace App\Http\Middleware;
use Closure;
class JsonApplication
{
    public function handle($request, Closure $next)
    {
        $request->headers->set('Accept', 'application/json');
        return $next($request);
    }
}

Затем зарегистрируйте промежуточное программное обеспечение глобально в ядре и примените все запросы API (здесь, поскольку проект является проектом веб-API, пространство имен routes/api. php удален, поэтому ключом в $middlewaregroups является API)

namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    protected $middlewareGroups = [
        'api' => [
            ......
            'json_application',
        ],
    ];
    protected $routeMiddleware = [
        ......
        'json_application' => \App\Http\Middleware\JsonApplication::class,
    ];
}

Таким образом, вы никогда не сможете беспокоиться о вызове интерфейса после завершения настройки и возврата кода страницы.

Вопрос 2: интерфейс возвращает унифицированный формат JSON

Данные, возвращаемые через вышеуказанный интерфейс конфигурации, находятся в формате JSON, но если вы продолжите разработку, вы обнаружите, что вам все равно нужно использовать код состояния HTTP, чтобы определить, успешно это или нет, и тогда различные интерфейсы возвращаемого ключа в JSON сильно отличаются, даже если один и тот же интерфейс успешен или ошибочен, он вернет разные ключи. Эта проблема в основном связана с проблемой возврата к тому же формату. Поскольку многие интерфейсы были написаны в Vue ранее, по-прежнему используется предыдущий ключевой режим

{
    "code": "0",
    "msg": "ok",
    "data": ""
}

Но как вернуть этот формат в laravel, стало проблемой. После нескольких поисков в Интернете хорошего решения не найдено, большинство из которых являются неполным охватом. Более того, код ошибки и информация об ошибке записаны на уровне логики, и вновь добавленные не знают, существует ли вообще какой-либо конфликт. Позже я долго искал BD и GG. Я также попытался использовать механизм исключений и промежуточное программное обеспечение, предоставляемые laravel, но меня это не удовлетворило. Как мы все знаем из Java, очень удобно иметь дело с кодами ошибок на Java. Определите перечисление напрямую и запишите в него все коды ошибок. При возникновении исключения перечисление передается в качестве параметра. Аналогично этому перечислению

package *.*.*
public enum ErrorCode {
    OK("ok", 0),
    PARAM_ERROR("param error", 88888),
    UNKNOWN_ERROR("unknown error", 99999);
    ErrorCode(String value, Integer key) {
        this.value = value;
        this.key = key;
    }
    private String value;
    private Integer key;
    public String getValue() {
        return value;
    }
    public Integer getKey() {
        return key;
    }
}

Класс исключений

package *.*.*;
import *.*.*.ErrorCode;
public class ApiException extends Exception {
    public int code = 0;
    public ApiException(ErrorCode errorCode) {
        super(errorCode.getValue());
        this.code = errorCode.getKey();
    }
    ......
}

Воспользуйся

throw new ApiException(ErrorCode.UNKNOWN_ERROR);

Поэтому я проверил перечисление PHP, которое действительно поддерживается, но после тщательного изучения я обнаружил, что перечисление PHP не только требует установки и открытия SPL, но и предоставленный метод бесполезен, поэтому я написал копию базового класса Java

namespace App\Enums;
abstract class Enum
{
    public static function __callStatic($name, $arguments)
    {
        return new static(constant('static::' . $name));
    }
}

Код ошибки здесь должен быть отмечен во взгляде из-за волшебного метода

namespace App\Enums;
/**
 * @method static CodeEnum OK
 * @method static CodeEnum ERROR
 */
class CodeEnum extends Enum
{
    public const OK = ['0', 'ok'];
    public const ERROR = ['99999', 'fail'];
    private $code;
    private $msg;
    public function __construct($param)
    {
        $this->code = reset($param);
        $this->msg = end($param);
    }
    public function getCode()
    {
        return $this->code;
    }
    public function getMsg()
    {
        return $this->msg;
    }
}

Пользовательский класс исключений

namespace App\Exceptions;
use App\Enums\CodeEnum;
use Exception;
use Illuminate\Support\Facades\Log;
class ApiException extends Exception
{
    public function __construct(CodeEnum $enum)
    {
        parent::__construct($enum->getMsg(), $enum->getCode());
    }
    public function report()
    {
        Log::error("ApiException {$this->getFile()}({$this->getLine()}): code({$this->getCode()}) msg({$this->getMessage()})");
    }
    public function render($request)
    {
        return response([
            'code' => $this->getCode(),
            'msg' => $this->getMessage(),
            'data' => ''
        ]);
    }
}

вызов

Throw new apiexception (New codeenum (codeenum:: error)); // it doesn't look good in this way
Throw new apiexception (codeenum:: ok()); // in this way, the call is similar to the Java call

===========Продолжение следует============