environment

PHP8 + MySQL5.7 + Nginx1.20
IDE: PhpStorm

build

1. Installation

  1. Install via Composer
    composer create-project laravel/laravel example-app

    2, through the Laravel installer

    
    composer global require laravel/installer

laravel new example-app


### Second, configuration
1. Database (configure the .env file in the root directory)

DB_CONNECTION=mysql
// host address
DB_HOST=127.0.0.1
// The port number
DB_PORT=3306
// data storage name
DB_DATABASE=laravel9
// username
DB_USERNAME=root
// password
DB_PASSWORD=

2. Time zone (configure config/app.php file)
````php
// Time zone modification, I feel that both can be defined by myself according to the actual situation
'timezone' => 'PRC', // continental time
or
'timezone' => 'Asia/Shanghai' // Shanghai time

Three, install the extension package

Only list a few necessary for the project, if necessary, you can take a look from the link below

  1. Code prompt tool
    composer require barryvdh/laravel-ide-helper --dev
  2. Language Pack
    composer require caouecs/laravel-lang

    Use: Put the vendor/caouecs/laravel-lang/src/zh-CN file in the resources/lang directory, if it is laravel9, put it directly in the root directory ```lang ```` directory

Modify config/app:

'locale' => 'zh_CN',
  1. Development and debugging tool (debugbar is installed in the dev environment)
    composer require barryvdh/laravel-debugbar --dev

Unified Response response

I don't use dingo for development here. Personally, it's not very easy to use. We define it ourselves below.
First, we need to create a Helpers directory under the app directory

  1. Encapsulating a unified status code (ResponseEnum)
    Create a ResponseEnum.php file in the app/Helpers directory
    
    <?php

namespace App\Helpers;

class ResponseEnum
{
// 001 ~ 099 means system status; 100 ~ 199 means authorized service; 200 ~ 299 means user service

/*------------------------------------------------ -------------------------------------------*/
// The beginning of 100 indicates information prompt, this kind of status indicates a temporary response
// 100 - continue
// 101 - switch protocol


/*------------------------------------------------ -------------------------------------------*/
// 200 means the server successfully accepted the client request
const HTTP_OK = [200001, 'The operation succeeded'];
const HTTP_ERROR = [200002, 'Operation failed'];
const HTTP_ACTION_COUNT_ERROR = [200302, 'Frequent operations'];
const USER_SERVICE_LOGIN_SUCCESS = [200200, 'Login successful'];
const USER_SERVICE_LOGIN_ERROR = [200201, 'Login failed'];
const USER_SERVICE_LOGOUT_SUCCESS = [200202, 'Logout successful'];
const USER_SERVICE_LOGOUT_ERROR = [200203, 'Logout failed'];
const USER_SERVICE_REGISTER_SUCCESS = [200104, 'Registration successful'];
const USER_SERVICE_REGISTER_ERROR = [200105, 'Registration failed'];
const USER_ACCOUNT_REGISTERED = [23001, 'The account is registered'];


/*------------------------------------------------ -------------------------------------------*/
// The one at the beginning of 300 indicates that the server redirects and points to other places, and the client browser must take more actions to realize the request
// 302 - The object has moved.
// 304 - Not modified.
// 307 - Temporary redirect.


/*------------------------------------------------ -------------------------------------------*/
// The ones at the beginning of 400 indicate that the client has an error request error, the data cannot be requested, or cannot be found, etc.
// 400 - Bad Request
const CLIENT_NOT_FOUND_HTTP_ERROR = [400001, 'Request failed'];
const CLIENT_PARAMETER_ERROR = [400200, 'Parameter error'];
const CLIENT_CREATED_ERROR = [400201, 'Data already exists'];
const CLIENT_DELETED_ERROR = [400202, 'Data does not exist'];
// 401 - Access Denied
const CLIENT_HTTP_UNAUTHORIZED = [401001, 'Authorization failed, please log in first'];
const CLIENT_HTTP_UNAUTHORIZED_EXPIRED = [401200, 'The account information has expired, please log in again'];
const CLIENT_HTTP_UNAUTHORIZED_BLACKLISTED = [401201, 'The account is logged in on another device, please log in again'];
// 403 - Forbidden
// 404 - file or directory not found
const CLIENT_NOT_FOUND_ERROR = [404001, 'The page was not found'];
// 405 - HTTP verb not allowed to access this page (method not allowed)
const CLIENT_METHOD_HTTP_TYPE_ERROR = [405001, 'HTTP request type error'];
// 406 - The client browser does not accept the MIME type of the requested page
// 407 - Proxy authentication required
// 412 - precondition failed
// 413 - Request entity too large
// 414 - Request URI too long
// 415 - Unsupported media type
// 416 - The requested range cannot be satisfied
// 417 - Execution failed
// 423 - Locked error


/*------------------------------------------------ -------------------------------------------*/
// The beginning of 500 indicates a server error, the server is terminated due to code, or for some reason
// Server operation error code: 500 ~ 599 at the beginning, followed by 3 digits
// 500 - Internal server error
const SYSTEM_ERROR = [500001, 'Server Error'];
const SYSTEM_UNAVAILABLE = [500002, 'The server is under maintenance and temporarily unavailable'];
const SYSTEM_CACHE_CONFIG_ERROR = [500003, 'Cache configuration error'];
const SYSTEM_CACHE_MISSED_ERROR = [500004, 'cache miss'];
const SYSTEM_CONFIG_ERROR = [500005, 'System configuration error'];

// Business operation error code (external service or internal service call)
const SERVICE_REGISTER_ERROR = [500101, 'Registration failed'];
const SERVICE_LOGIN_ERROR = [500102, 'Login failed'];
const SERVICE_LOGIN_ACCOUNT_ERROR = [500103, 'Account or password error'];
const SERVICE_USER_INTEGRAL_ERROR = [500200, 'Insufficient points'];

//501 - The header value specifies an unimplemented configuration
//502 - The web server received an invalid response when acting as a gateway or proxy server
//503 - Service unavailable. This error code is specific to IIS 6.0
//504 - Gateway timed out
//505 - HTTP version not supported
/*------------------------------------------------ -------------------------------------------*/

}

2. Create a business exception capture Exception file
Create a ```BusinessException.php``` file in the ```app/Exceptions``` directory for throwing business exceptions
````php
<?php

namespace App\Exceptions;

useException;

class BusinessException extends Exception
{
    /**
     * Business exception constructor
     * @param array $codeResponse status code
     * @param string $info Custom return information, if not empty, the message text information in codeResponse will be replaced
     */
    public function __construct(array $codeResponse, $info = '')
    {
        [$code, $message] = $codeResponse;
        parent::__construct($info ?: $message, $code);
    }
}
  1. Custom return exception
    Modify the Handler.php file in the app/Exceptions directory
    
    <?php

namespace App\Exceptions;

use App\Helpers\ApiResponse;
use App\Helpers\ResponseEnum;
use Illuminaate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

class Handler extends ExceptionHandler
{
useApiResponse;

/**
 * A list of the exception types that are not reported.
 *
 * @var array<int, class-string<Throwable>>
 */
protected $dontReport = [
    //
];

/**
 * A list of the inputs that are never flashed for validation exceptions.
 *
 * @var array<int, string>
 */
protected $dontFlash = [
    'current_password',
    'password',
    'password_confirmation',
];

/**
 * Register the exception handling callbacks for the application.
 *
 * @return void
 */
public function register()
{
    $this->reportable(function (Throwable $e) {
        //
    });
}

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

// If it is a production environment, return 500
if (!config('app.debug')) {
$this->throwBusinessException(ResponseEnum::SYSTEM_ERROR);
}
// request type error exception thrown
if ($exception instanceof MethodNotAllowedHttpException) {
$this->throwBusinessException(ResponseEnum::CLIENT_METHOD_HTTP_TYPE_ERROR);
}
// Parameter validation error exception is thrown
if ($exception instanceof ValidationException) {
$this->throwBusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR);
}
// Route does not exist exception thrown
if ($exception instanceof NotFoundHttpException) {
$this->throwBusinessException(ResponseEnum::CLIENT_NOT_FOUND_ERROR);
}
// custom error exception thrown
if ($exception instanceof BusinessException) {
return response()->json([
'status' => 'fail',
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
'data' => null,
'error' => null,
]);
}
return parent::render($request, $exception);
}
}

Fourth, encapsulate the unified message (ApiResponse) returned by the API
Create ```ApiResponse.php``` file in ```app/Helpers``` directory
````php
<?php


namespace App\Helpers;

use App\Helpers\ResponseEnum;
use App\Exceptions\BusinessException;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;


trait ApiResponse
{
    /**
     * success
     * @param null $data
     * @param array $codeResponse
     * @return JsonResponse
     */
    public function success($data = null, $codeResponse=ResponseEnum::HTTP_OK): JsonResponse
    {
        return $this->jsonResponse('success', $codeResponse, $data, null);
    }

    /**
     * fail
     * @param array $codeResponse
     * @param null $data
     * @param null $error
     * @return JsonResponse
     */
    public function fail($codeResponse=ResponseEnum::HTTP_ERROR, $data = null, $error=null): JsonResponse
    {
        return $this->jsonResponse('fail', $codeResponse, $data, $error);
    }

    /**
     *json response
     * @param $status
     * @param $codeResponse
     * @param $data
     * @param $error
     * @return JsonResponse
     */
    private function jsonResponse($status, $codeResponse, $data, $error): JsonResponse
    {
        list($code, $message) = $codeResponse;
        return response()->json([
            'status' => $status,
            'code' => $code,
            'message' => $message,
            'data' => $data ?? null,
            'error' => $error,
        ]);
    }


    /**
     * Successful paging return
     * @param $page
     * @return JsonResponse
     */
    protected function successPaginate($page): JsonResponse
    {
        return $this->success($this->paginate($page));
    }

    private function paginate($page)
    {
        if ($page instanceof LengthAwarePaginator){
            return [
                'total' => $page->total(),
                'page' => $page->currentPage(),
                'limit' => $page->perPage(),
                'pages' => $page->lastPage(),
                'list' => $page->items()
            ];
        }
        if ($page instanceof Collection){
            $page = $page->toArray();
        }
        if (!is_array($page)){
            return $page;
        }
        $total = count($page);
        return [
            'total' => $total, //Total data
            'page' => 1, // current page number
            'limit' => $total, // the number of data bars per page
            'pages' => 1, // the page number of the last page
            'list' => $page // data
        ];
    }

    /**
     * Business exception return
     * @param array $codeResponse
     * @param string $info
     * @throws BusinessException
     */
    public function throwBusinessException(array $codeResponse=ResponseEnum::HTTP_ERROR, string $info = '')
    {
        throw new BusinessException($codeResponse, $info);
    }
}
  1. Create a base controller class
  2. Create a BaseController.php in the app/Http/controller directory as the base class of Api, and then inherit Controller in the base class BaseController.php , and introduce the unified message returned by the encapsulation APImessage (ApiResponse)
    
    <?php

namespace App\Http\Controllers;

use App\Helpers\ApiResponse;

class BaseController extends Controller
{
// API interface response
useApiResponse;
}

6. Use
1. Return success information
````php
return $this->success($data);
  1. Return failure information
    return $this->fail($codeResponse);
  2. Throwing an exception
    $this->throwBusinessException($codeResponse);
  3. Paging
    return $this->successPaginate($data);

    Unified form parameter input validation

  4. Create
    Create a VerifyRequestInput.php file in the App\Helpers directory, and introduce ApiResponse, so that the form parameters can be verified more easily, among which `verifyData` method to customize validation fields and rules
    
    <?php

namespace App\Helpers;

use App\Helpers\ResponseEnum;
use App\Exceptions\BusinessException;
use Illuminate\Validation\Rule;

trait VerifyRequestInput
{
useApiResponse;

/**
 * Verify ID
 * @param $key
 * @param null $default
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyId($key, $default=null)
{
    return $this->verifyData($key, $default, 'integer|digits_between:1,20');
}

/**
 * Check if it is an integer
 * @param $key
 * @param null $default
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyInteger($key, $default=null)
{
    return $this->verifyData($key, $default, 'integer');
}

/**
 * Verify if it is a number
 * @param $key
 * @param null $default
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyNumeric($key, $default=null)
{
    return $this->verifyData($key, $default, 'numeric');
}

/**
 * Check if it is a string
 * @param $key
 * @param null $default
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyString($key, $default=null)
{
    return $this->verifyData($key, $default, 'string');
}

/**
 * Check if it is a boolean
 * @param $key
 * @param null $default
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyBoolean($key, $default=null)
{
    return $this->verifyData($key, $default, 'boolean');
}

/**
 * Verify if it is an enumeration
 * @param $key
 * @param null $default
 * @param array $enum
 * @return mixed|null
 * @throws BusinessException
 */
public function verifyEnum($key, $default=null, array $enum=[])
{
    return $this->verifyData($key, $default, Rule::in($enum));
}

/**
  • Custom verification parameters
    • @param $key string field
    • @param $default string default value
    • @param $rule string validation rule
    • @return mixed|null
    • @throws BusinessException
      */
      public function verifyData($key, $default, $rule)
      {
      $value = request()->input($key, $default);
      $validator = \Validator::make([$key => $value], [$key => $rule]);
      if (is_null($value)){
      $this->throwBusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR);
      }
      if ($validator->fails()){
      $this->throwBusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, $validator->errors()->first());
      }
      return $value;
      }

}

2. Use
```VerifyRequestInput``` needs to be introduced in the ```App\Http\Controllers\BaseController``` controller base class
````php
use App\Helpers\VerifyRequestInput;

// Validate the form parameter input request
use VerifyRequestInput;
  1. Case:
    There is a index method, we use verifyId to verify the parameters of the request when getting the parameters
    public function index()
    {
     $id = $this->verifyId('id', null);
    }

    When we request, because the incoming parameter is a string

    http://127.0.0.1:8000/api/user/index?id=xddd

    So return `The id must be an integer , prompting that the id must be an integer

Create service layer Service

If the project is relatively small and there are few interfaces, the business logic can be placed in the controller and model layers. Otherwise, you need to create a Service layer to store some more complex business logic.

  1. In the ``app`directory, create a folder namedServices```

  2. Create the base class BaseService.php in the newly created Services directory, and use the singleton mode to avoid wasting memory and make it easy to call

    
    <?php

namespace App\Services;

use App\Helpers\ApiResponse;

class BaseService
{
// Introduce api unified return message
useApiResponse;

protected static $instance;

public static function getInstance()
{
    if (static::$instance instanceof static){
        return self::$instance;
    }
    static::$instance = new static();
    return self::$instance;
}

protected function __construct(){}

protected function __clone(){}

}

3. Use
For example, to implement a function to obtain user information
1. Create a ``UserService.php``` file in the Service layer
````php
<?php

namespace App\Services;

use App\Services\BaseService;

class UserService extends BaseService
{
    // get user information
    public function getUserInfo()
    {
        return ['id' => 1, 'nickname' => 'Zhang San', 'age' => 18];
    }

}
  1. Add a info method in the controller UserController, and call the getUserInfo() method in the service layer
    
    use App\Services\UserService;

public function info()
{
$user = UserService::getInstance()->getUserInfo();
return $this->success($user);
}


3. Return

![image.png](https://cdn.elephdev.com/uploads/20220328/26be2011a059aa8c85777c53bede9fb9.png)
点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部