xepozz/yii2-api-model-presenter

该包最新版本(0.0.1)的许可信息不可用。

API模型展示器。

安装: 0

依赖者: 0

建议者: 0

安全: 0

星标: 0

关注者: 2

分支: 0

开放问题: 0

类型:yii2-extension

0.0.1 2020-02-05 19:02 UTC

This package is auto-updated.

Last update: 2024-09-15 10:15:05 UTC


README

Build Status

安装

composer req xepozz/yii2-api-model-presenter

描述

在处理API时,需要将对象的属性以JSON或XML的结构返回。

Yii2内置了将模型以JSON或XML形式显示的机制。

看起来是这样的

class User extends \yii\db\ActiveRecord
{
    public $firstName;
    public $lastName;

    public function fields()
    {
        return [
            'id' => 'id',
            'name' => function() {             
                return $this->firstName . ' ' . $this->lastName;
            },
        ];
    }
}

问题

  1. 第一种问题的缺点是,模型被强制知道在序列化时将转换为哪种结构。

  2. 第二个问题出现在有模型继承的情况下。
    示例
    存在common\models\Userapi\modules\chat\models\Userapi\modules\forum\models\User(强烈建议不要这样做)如果直接返回要显示的模型,那么一切都很好。但如果某个模块返回common\models\User而不是api\modules\chat\models\User,那么就需要采取一些技巧来在API中返回所需的格式。这种技巧通常是这样的

       /** @var $model \common\models\User */
       $model = $someService->getMyUser();
       
       return \api\modules\chat\models\User::findOne($model->id);

    或者相反,当需要输出common\models\User中描述的结构,而不是api\modules\chat\models\User中内置的结构。

       /** @var $model \api\modules\chat\models\User */
       $model = $someService->getMyUser();
       
       return \common\models\User::findOne($model->id);

    老实说,这看起来就像是一个接一个的补丁。

  3. 第三个问题是从前一个问题中产生的。
    如果使用了第2点中的模型,那么一个糟糕的程序员可能会想在输出api\modules\chat\models\User模型时输出api\modules\chat\models\Message(它继承自common\models\Message),而不是输出作为关系的模型。
    但在common\models\User中,关系被定义为common\models\Message,该怎么办?只需要用一个手指就可以通过在api/...中覆盖模型来解决这个问题。

解决方案

我提出以下方法来解决这个问题

有一个类,其中描述了所有将被发送到API的行为。
可以在这个类中加载任何模型集合。输出结构总是相同的。

示例

对象代理的简单使用示例。
use Xepozz\Yii2ApiModelPresenter\ProxyPresenter;

/**
 * @property \common\models\User $record
 */
class UserPresenter extends ProxyPresenter
{
    protected function getFields(): array
    {
        return [
            'first_name',
            'last_name',
            'full_name' => function() {
                return sprintf('%s %s', $this->record->first_name, $this->record->last_name);        
            }
        ];
    }
}
更高级的使用示例。

使用关系展示器来输出关系。

use Xepozz\Yii2ApiModelPresenter\ProxyPresenter;

/**
 * @property \common\models\User $record
 */
class UserPresenter extends ProxyPresenter
{
    protected function getFields(): array
    {
        return [
            // ...
        ];
    }

    public function getExtraFields(): array
    {
        return [
            'messages' => 'chatMessages',
        ];
    }

    protected function setUpChildDefinitions(): array
    {
        return [
            'chatMessages' => ChatMessagePresenter::class,
        ];
    }
}
带有可选隐藏字段的示例
use Xepozz\Yii2ApiModelPresenter\ProxyPresenter;

/**
 * @property \common\models\User $record
 */
class UserPresenter extends ProxyPresenter
{
    protected function getFields(): array
    {
        return [
            'id',
            'status',
            'last_visited_at',
        ];
    }

    protected function getIgnoredFields(): array
    {
        return [
            /**
             * Скрываем на "prod" откружении поле email. Используется только для разработки
             */
            'id' => YII_ENV_PROD,
            'last_visited_at' => function() {
                /**
                 * Если статус online, тогда не показываем это поле.
                 */
                return (bool) $this->record->status;
            },
        ];
    }
}

发展

我很乐意接受任何改进、评论以及关于进一步发展库的各种讨论。
目前有一个计划,包括以下任务

  • 需要编写测试
  • 编写更清晰的文档
  • 将文档翻译成英文