xepozz / yii2-api-model-presenter
API模型展示器。
Requires
- yiisoft/yii2: ~2.0.0
Requires (Dev)
- phpunit/phpunit: ^5.0
This package is auto-updated.
Last update: 2024-09-15 10:15:05 UTC
README
安装
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; }, ]; } }
问题
-
第一种问题的缺点是,模型被强制知道在序列化时将转换为哪种结构。
-
第二个问题出现在有模型继承的情况下。
示例
存在common\models\User
、api\modules\chat\models\User
、api\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);
老实说,这看起来就像是一个接一个的补丁。
-
第三个问题是从前一个问题中产生的。
如果使用了第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; }, ]; } }
发展
我很乐意接受任何改进、评论以及关于进一步发展库的各种讨论。
目前有一个计划,包括以下任务
- 需要编写测试
- 编写更清晰的文档
- 将文档翻译成英文