种种历史原因,导致无法使用使用严格的 RESTful 规则, 这里只是内部项目迁移过程中给大家普及的一点点小知识,因为是内部项目,对您可能并不通用。

Yii2 basic 项目结构

├── codeception.yml
├── commands
├── components
├── composer.json
├── composer.lock
├── config
├── controllers
├── messages
├── models
├── runtime
├── service
├── tests
├── vendor
├── web
├── yii
└── yii.bat
  • API 规范
  • route
  • controllers
  • models
  • service
  • guzzlephp
  1. API 简约规范 因为历史和现行的原因,不采用严格的 RESTful 定义的标准

  2. route 映射规则

'PUT <controller>/<id>'      => '<controller>/update',
'DELETE <controller>/<id>'   => '<controller>/delete',
'GET <controller>/<id>'      => '<controller>/view',
'POST <controller>'          => '<controller>/create',
'GET <controller>'           => '<controller>/index',

注: URL 驼峰式命名,需要用 - 分割,例如

'GET pointAccount' => 'point-account/index',

新代码尽量不要采用这种风格,应该尽量采用单个英文名词。

  1. controllers 统一继承自 MainController 需要注意的几个方法
beforeAction
afterAction

getRawBody  -> file_get_contents('php://input')
json
renderJson
  1. models 在项目中使用 ModelActiveRecord , 当前项目相关的父类是 MainModelMainActiveRecord
\app\components\ModelTrait
Model
ActiveRecord
  1. Service 是复杂业务和公共业务逻辑的抽象,保证 Controller 简单,不同入口的相同业务统一。
  2. Guzzlephp 一套特别好用的 Http Client ,告别自己封装 curl。

  3. 入参验证,有对应 db 的采用 MainActiveRecord 为父类,无 db 对应的采用 MainModel 为父类,通过统一的 Validator 和自定义验证规则来做入参校验,避免写各种 if else empty isset 等判断逻辑。

  4. 返回值问题
  • 结构统一 {“status”: integer(), “message”: string(), “data”: []}
  • 大小写永远保持一致
  • 类型明确

Codeception 安装

$ composer global require "codeception/codeception=2.0.*"
$ composer global require "codeception/specify=*"
$ composer global require "codeception/verify=*"
$ composer global status
Changed current directory to <directory>

$ export PATH="${PATH}:/<directory>/vendor/bin"
$ codecept -V
Codeception version 2.0.16

Codeception 功能介绍

  • Acceptance Testing 验收测试 (JS Ajax)
  • Functional Testing 功能测试 (No js)
  • API Testing
  • Unit Testing 单元测试
  1. Acceptance Testing 验收测试 (JS Ajax)
<?php
$I = new AcceptanceTester($scenario);
$I->amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', array(
'username' => 'MilesDavis',
'email' => 'miles@davis.com'
));
$I->see('Thank you for Signing Up!');
  1. Functional Testing 功能测试 (No js)
<?php
$I = new FunctionalTester($scenario);
$I->amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', array(
'username' => 'MilesDavis',
'email' => 'miles@davis.com'));
$I->see('Thank you for Signing Up!');
$I->seeEmailSent('miles@davis.com', 'Thank you for registration');
$I->seeInDatabase('users', array('email' => 'miles@davis.com'));
  1. API Testing
<?php
$I = new ApiTester($scenario);
$I->wantTo('create a new user by API');
$I->amHttpAuthenticated('davert','123456');
$I->haveHttpHeader('Content-Type','application/x-www-form-urlencoded');
$I->sendPOST('/users', array('name' => 'davert' ));
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
$I->seeResponseContainsJson(array('result' => 'ok'));
  1. Unit Testing 单元测试
<?php
use \Codeception\Util\Stub;
class UserTest extends \Codeception\TestCase\Test
{
public function testUserSave() {
$user = Stub::make('User');
$user->setName('davert');
$this->assertEquals('davert', $user->getName());
$user->save();
$this->tester->seeInDatabase('users', array('name' => 'davert'));
}
}