PHP builds a high-performance API architecture based on SW-X framework

Posted by nikes90 on Fri, 04 Mar 2022 08:05:05 +0100

preface

Official website address: SW-X framework - PHP swoolex framework focusing on high-performance and convenient development

I hope the big guys raise their hands and give my little brother a star: https://github.com/swoolex/swoolex

1. 404 interface configuration

In the HTTP service, when the corresponding route cannot be found, it will load / config / route 404 configuration in PHP configuration file.

The following are specific parameter configuration items:

<?php
return [
    // Do you want to enable custom error handlers when a route cannot be found
    '404' => true,
    // The custom error handler only needs to provide the namespace location of a class
    'error_class' => '\\box\\http_error',
];

Now let's open / box/http_error.php file and modify it to the following code:

<?php
namespace box;
use \x\controller\Http;

class http_error  extends Http{

    /**
     * entrance
     * @todo nothing
     * @author Little yellow cattle
     * @version v1.0.1 + 2020.05.29
     * @deprecated Not enabled temporarily
     * @global nothing
     * @return void
    */
    public function __construct() {
        return \x\Restful::code(\x\Restful::ONROUTE())->callback();
    }
}

Because the above uses the \ x\Restful component and throws an ONROUTE status code, the corresponding Restful configuration should also be modified:

/restful/default/code.php is modified to the following code:

<?php
return [
    'ERROR' => 0, // Default failure status code
    'SUCCESS' => 1, // Default success status code
    'ACTION_ERROR' => 40001, // Permission verification failed
	'ONROUTE' => 40004, // Interface that does not exist
];

/restful/default/msg.php is modified to the following code:

<?php
return [
    // tips corresponding to the default error status code
    'ERROR' => [
        'default' => 'request was aborted', // Default value
    ],
    // tips corresponding to the default success status code
    'SUCCESS' => [
        'default' => 'Request succeeded', // Default value
		'test' => 'test msg',
    ],
    // Permission verification failed
    'ACTION_ERROR' => [
        'default' => 'Permission verification failed', // Default value
    ],
    // Interface that does not exist
    'ONROUTE' => [
        'default' => 'The interface does not exist', // Default value
    ],
];

At this time, any one of our interfaces does not exist, http://IP Address: port / api/user/info, you can see that the framework throws the following status code:

{
  "code": 40004,
  "msg": "The interface does not exist",
  "data": []
}

2. Request type restrictions

There are many ways to limit the request type of an HTTP controller in SW-X,

The first is to use @ Post, @ Get, @ Ajax annotations for restriction.

The second is to use the \ x\Validate validator component to judge and filter the request header.

The first method is generally recommended because it is very flexible, while the second method is generally used to filter the same request header for some interfaces in the same group, such as signature judgment.

Next, we will / APP / HTTP / v1_ 0_ 1/controller/shop/delete. The code of PHP controller is changed as follows:

<?php
namespace app\http\v1_0_1\controller\shop;
use x\controller\Http;
// Introducing Restful components
use x\Restful;

class delete extends Http
{
    /**
     * I only allow Post+Ajax requests
     * @Post
     * @Ajax
    */
    public function index() {
		// Restful component throws interface response
		return Restful::code(Restful::SUCCESS())->data('Your request has been approved')->callback();
	}
}

At the same time, the error message of this annotation is generated by / box / lifecycle / route_ error. We need to change the PHP file to the following code for callback:

<?php
namespace box\lifecycle;

class route_error
{
    /**
     * Special conversion of Msg values of 3 annotations
    */
    private $tips = [
        'Route Method Get'  => 'Only allowed Get request',
        'Route Method Post' => 'Only allowed Post request',
        'Route Method Ajax' => 'Only allowed Ajax request',
    ];
    /**
     * Accept callback processing
     * @todo nothing
     * @author Little yellow cattle
     * @version v1.1.5 + 2020.07.15
     * @deprecated Not enabled temporarily
     * @global nothing
     * @param Swoole $server Service instance
     * @param string $fd Client ID
     * @param string $status Error event status code
     * @return bool
    */
    public function run($server, $fd, $status) {
        $tips = 'Annotate: SW-X Status: '.$status.' ERROR !';

        $type = \x\Config::get('server.sw_service_type');
        // Throw that handles only HTTP service requests
        if ($type == 'http') {
            if (isset($this->tips[$status])) $tips = $this->tips[$status];
            return \x\Restful::code(\x\Restful::LIFECYCLE())->setMsg($tips)->callback();
        }
        return true;
    }
}

Because the above uses the \ x\Restful component and throws a LIFECYCLE status code, the corresponding Restful configuration should also be modified:

/restful/default/code.php is modified to the following code:

<?php
return [
    'ERROR' => 0, // Default failure status code
    'SUCCESS' => 1, // Default success status code
    'ACTION_ERROR' => 40001, // Permission verification failed
	'ONROUTE' => 40004, // Interface that does not exist
    'LIFECYCLE' => 20001, // Route lifecycle error callback status code [use custom MSG]
];

Note that after the life cycle file is modified, the hot overload is invalid. You need to manually stop and re start the service.

After the restart, we will visit again http://IP Address: port / api/shop/delete interface, you can see that the framework throws the following status code:

{
  "code": 20001,
  "msg": "Only allowed Post request",
  "data": []
}

If the test request is successful, you can use tools such as Postman or Jquery to send a post Ajax request.

3. Validate verify form data

For SW-X, it is recommended to use the \ x\Validate validator component to judge and filter requests.

For specific usage, please refer to the official documents: https://www.sw-x.cn/word/v2.5.x/vali_explain.html

Next, let's create a Shop validator for API requests for commodity grouping.

Create validator file / box / validate / shop PHP, the writing code is as follows:

<?php
namespace box\validate;
use x\Validate;

class Shop extends Validate
{
    // Define rules corresponding to fields
    protected $rule = [
        'id' => 'require|int',
        'title'  =>  'require|min:10|max:20',
        'info.des' =>  'min:10|max:20',
    ];
    // Custom error value declaration
    protected $message  =   [
        'id.require'   => '{id}Forgot to enter',
        'title.min'     => '{title}Cannot be less than{0}',
        'title.max'     => '{title}Cannot be greater than{0}',
        'info.des.min' => '{:preset}Cannot be less than{0}',
        'info.des.min' => '{info.des}Cannot be greater than{0}',
    ];
    // Scene definition
    protected $scene = [
        // Scene used when modifying (abbreviation)
        'edit'  =>  ['id','info.des'], // Fields to be verified
        // Scene used when deleting (abbreviation)
        'delete'  =>  ['id'], // Fields to be verified
    ];
}

Next, we will / APP / HTTP / v1_ 0_ 1/controller/shop/delete. The code of PHP controller is changed as follows:

<?php
namespace app\http\v1_0_1\controller\shop;
use x\controller\Http;
// Introducing Restful components
use x\Restful;

class delete extends Http
{
    /**
     * Using annotation binding validators
     * @Validate(class="\box\validate\Shop", scene="delete")
    */
    public function index() {
		// Restful component throws interface response
		return Restful::code(Restful::SUCCESS())->data('Check passed')->callback();
	}
}

At the same time, because the error message of this annotation is generated by / box/lifecycle/validate_error.php lifecycle file for callback processing, so we also need to change the file to the following code:

<?php
namespace box\lifecycle;

class validate_error
{
    /**
     * Accept callback processing
     * @todo nothing
     * @author Little yellow cattle
     * @version v2.5.6 + 2021-09-15
     * @deprecated Not enabled temporarily
     * @global nothing
     * @param string $server_type Service type http/websocket/rpc/mqtt
     * @param bool $batch Filter all
     * @param array $errors Error validation result set
     * @return bool
    */
    public function run($server_type, $batch, $errors) {
        // $batch is used to execute all filtering rules and return all error reasons together
        // The default lifecycle returns only the first error reason
        $error = $errors[0]['intact_field'].' => '.$errors[0]['message'];

        // Throw that handles only HTTP service requests
        if ($server_type == 'http') {
            return \x\Restful::code(\x\Restful::VALIDATE())->setMsg($errors[0]['message'])->callback();
        }
        return true;
    }
}

Because the above uses the \ x\Restful component and throws a valid status code, the corresponding Restful configuration should also be modified:

/restful/default/code.php is modified to the following code:

<?php
return [
    'ERROR' => 0, // Default failure status code
    'SUCCESS' => 1, // Default success status code
    'ACTION_ERROR' => 40001, // Permission verification failed
	'ONROUTE' => 40004, // Interface that does not exist
    'LIFECYCLE' => 20001, // Route lifecycle error callback status code [use custom MSG]
    'VALIDATE' => 20002, // Verifier life cycle error callback status code [use custom MSG]
];

Note that after the life cycle file is modified, the hot overload is invalid. You need to manually stop and re start the service.

After the restart, we will visit again http://IP Address: port / api/shop/delete interface, you can see that the framework throws the following status code:

{
  "code": 20002,
  "msg": "id Forgot to enter",
  "data": []
}

visit http://IP Address: port / api/shop/delete?id=1, you can pass the verification scenario of delete.

Topics: PHP architecture swoole