4spacesdk/ci4restextension

CodeIgniter 4 的 REST 扩展


README

CodeIgniter 4 的 REST 扩展

应与 ORM 扩展 一同使用。

启用 API 管理

如果与 认证扩展 一起使用,您可以利用更多 API 功能,例如访问日志和作用域授权。

步骤 1)

安装 认证扩展

步骤 2)

添加配置文件 RestExtension.php

<?php namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\HTTP\Request;
use RestExtension\AuthorizeResponse;

class RestExtension extends BaseConfig {

    /*
     * Enabling this feature requires you to
     * - Store routes in the database
     * - Assign scopes to the routes
     * This will allow RestExtension to authorize every request against OAuth2 Scopes
     */
    public $enableApiRouting        = FALSE;

    /*
     * Track every access to the API.
     * Consider adding a CronJob to periodically cleanup this table
     */
    public $enableAccessLog         = FALSE;

    /*
     * Track blocked requests.
     * Ex. if you use scopes to authorize
     */
    public $enableBlockedLog        = FALSE;

    /*
     * Track errors
     */
    public $enableErrorLog          = FALSE;

    /*
     * Enable rate limit
     */
    public $enableRateLimit         = TRUE;

    /*
     * Hourly rate limit
     * Requires enableAccessLog to be TRUE
     */
    public $defaultRateLimit        = 0;

    /*
     * Daily usage report
     */
    public $enableUsageReporting    = FALSE;


    /**
     * Apply function to authenticate $request.
     * access_token is placed in either a header called Authorization or a GET-parameter called access_token
     * @param Request $request
     * @param string $scope
     * @return object
     */
    public function authorize(Request $request, $scope = null) {

        /**
         * If AuthExtension is part of this project you could do something like
         */
        return (object)\AuthExtension\AuthExtension::authorize($scope);


        /**
         * If AuthExtension is part of another project (ex. Micro Service) you could do something like
         */

//        $url = config('Domains')->auth.'/check?';
//        $url .= http_build_query(['scope' => $scope, 'access_token' => RestRequest::getInstance()->getAccessToken()]);
//
//        $ch = curl_init();
//        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//        curl_setopt($ch, CURLOPT_URL, $url);
//        $json = json_decode(curl_exec($ch));
//        curl_close($ch);
//        return $json;
    }

    /*
     * Provide Route for Typescript model exporter
     */
    public $typescriptModelExporterRoute    = 'export/models';

    /*
     * Provide Route for Typescript API exporter
     */
    public $typescriptAPIExporterRoute      = 'export/api/ts';

    /*
     * Provide Route for Typescript API exporter
     */
    public $vueAPIExporterRoute             = 'export/api/vue';

    /*
     * Provide Route for Xamarin model exporter
     */
    public $xamarinModelExporterRoute       = 'xamarin/models';

    /*
     * Provide Namespace for Xamarin API
     */
    public $xamarinAPIClassName             = 'Api';
    public $xamarinAPINamespace             = 'App.Http';
    public $xamarinBaseAPINamespace         = 'App.Http';

    /*
     * Provide Route for Xamarin API exporter
     */
    public $xamarinAPIExporterRoute         = 'xamarin/api';

    /*
     * Provide Namespace for Api request and response Interfaces
     */
    public $apiInterfaceNamespace           = 'App\Interfaces';

    /*
     * Provide base namespace for Controllers to be used in Api export
     */
    public $apiControllerNamespace          = 'App\Controllers';

    /*
     * Provide destination for TypeScript Models to be placed when executed as Command
     */
    public $typescriptModelExporterDestination  = '~/Desktop/ModelExporter';

    /*
     * Provide destination for TypeScript API to be placed when executed as Command
     */
    public $typescriptAPIExporterDestination    = '~/Desktop/APIExporter';

}

步骤 3)

将以下行添加到 Config/Events.phpEvents::on('pre_system', [\RestExtension\Hooks::class, 'preSystem']);。必须在 OrmExtension 之下。将此行添加到 Config/Events.phpEvents::on('pre_command', [\RestExtension\Hooks::class, 'preSystem']);。必须在 OrmExtension 之下。

步骤 4)

将以下行添加到您的迁移文件中 \RestExtension\Migration\Setup::migrateUp(); 并运行它。

查询解析器

将以下行添加到您的基控制器中

$this->queryParser = new QueryParser();
$this->queryParser->parseRequest($this->request);

如果您使用 Orm 扩展,将此特性添加到您的基模型中: use RestExtension\ResourceModelTrait; 或扩展 RestExtension\Core\Model。这将允许 Rest 扩展根据您的模型及其关系过滤资源。

示例

/milestones?filter=name:[Milepæl%202,Milepæl%201],project.id:9
通过名称过滤里程碑 "Milepæl 02" 或 "Milepæl 01" 并与 ID 为 9 的项目相关联。

/projects?filter=id:>=10,id:<=100,name:"SOME PROJECT"
通过 ID 大于等于 10 且小于等于 100 以及名称等于 "SOME PROJECT" 的项目进行过滤。

过滤

REST 扩展使用 RFS 过滤方法

 * Example
 * GET /items?filter=price:>=10,price:<=100.
 * This will filter items with price greater than or equal to 10 AND lower than or equal to 100. (>=10 & <=100)
 *
 * Filters are made up of rules, with a property, a value and an operator. Where property is the field you want to
 * filter against, e.g. featured, value is what you want to match e.g. true and operator is most commonly 'equals' e.g. :.
 *
 * When specifying a filter, the property and value are always separated by a colon :.
 * If no other operator is provided, then this is a simple 'equals' comparison.
 *
 * featured:true - return all posts where the featured property is equal to true.
 *
 * You can also do a 'not equals' query, by adding the 'not' operator - after the colon.
 * For example, if you wanted to find all posts which have an image,
 * you could look for all posts where image is not null: feature_image:-null.
 *
 * Filters with multiple rules
 * You can combine rules using either 'and' or 'or'. If you'd like to find all posts that are either featured,
 * or they have an image, then you can combine these two rules with a comma , which represents 'or':
 * filter=featured:true,feature_image:-null.
 *
 * If you're looking for all published posts which are not static pages,
 * then you can combine the two rules with a plus + which represents 'and': filter=status:published+page:false.
 * This is the default query performed by the posts endpoint.
 *
 * Syntax Reference
 * A filter expression is a string which provides the property, operator and value in the form property:operatorvalue:
 *
 *  -  property - a path representing the key to filter on
 *  -  : - separator between property and an operator-value expression
 *      -  operator is optional, so : on its own is roughly =
 *
 * Property
 * Matches: [a-zA-Z_][a-zA-Z0-9_.]
 *
 *  - can contain only alpha-numeric characters and _
 *  - cannot contain whitespace
 *  - must start with a letter
 *  - supports . separated paths, E.g. authors.slug or posts.count
 *  - is always lowercase, but accepts and converts uppercase
 *
 * Value
 * Can be one of the following
 *
 *  - null
 *  - true
 *  - false
 *  - a _number _(integer)
 *  - a literal
 *       - Any character string which follows these rules:
 *       - Cannot start with - but may contain it
 *       - Cannot contain any of these symbols: '"+,()><=[] unless they are escaped
 *       - Cannot contain whitespace
 *  - a string
 *       - ' string here ' Any character except a single or double quote surrounded by single quotes
 *       - Single or Double quote _MUST _be escaped*
 *       - Can contain whitespace
 *       - A string can contain a date any format that can be understood by new Date()
 *
 * Operators
 *  -   not operator
 *  >   greater than operator
 *  >=  greater than or equals operator
 *  <   less than operator
 *  <=  less than or equals operator
 *  ~   search, this will do an case insensitive like with % on both sides
 *
 * Combinations
 *  + - represents and OBS! Not supported
 *  , - represents or
 *  ( filter expression ) - overrides operator precedence OBS! Not supported
 *  [] - grouping for IN style, ex. tags:[first-tag,second-tag]

排序

ordering=PROPERTY:DIRECTION
可以通过逗号分隔应用多个排序。
例如 ?ordering=title:asc,created:desc

按关系排序
例如 ?ordering=created_by.first_name:asc
使用点号 . 分隔深层关系。请注意,关系名称总是单数形式

方向是可选的。

包含

include=RELATION
例如 ?include=created_by
例如 ?include=created_by.role
使用点号 . 分隔深层关系。请注意,关系名称总是单数形式

API 解析器

如果您以这种方式记录您的 API 端点

/**
 * @route /loads/{loadId}/calculate
 * @method get
 * @custom true
 * @param int $loadId parameterType=path
 * @parameter int[] $user_ids parameterType=query required=true
 * @parameter string $start parameterType=query required=true
 * @parameter string $end parameterType=query required=true
 */

Rest 扩展可以为您生成 Swagger 文档。

$parser = ApiParser::run();
$paths = $parser->generateSwagger();

$paths 附带到 Swagger 路径。

说明

  • @route 是不言而喻的。
  • @method 是不言而喻的。
  • @custom 如果不存在,Rest 扩展将添加默认参数:filter、include、offset、limit、ordering
  • @param & @parameter 是相同的。以类型开头,后跟名称。您可以指定参数类型和需求。