├── src ├── SwaggerUIAsset.php ├── index.php ├── SwaggerApiAction.php └── SwaggerAction.php ├── composer.json ├── LICENSE ├── README.md └── README_ZH.md /src/SwaggerUIAsset.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace light\swagger; 13 | 14 | use yii\web\AssetBundle; 15 | 16 | /** 17 | * Assets bundle for swagger-ui. 18 | */ 19 | class SwaggerUIAsset extends AssetBundle 20 | { 21 | public $sourcePath = '@bower/swagger-ui/dist'; 22 | public $baseUrl = '@web'; 23 | 24 | public $js = [ 25 | 'swagger-ui-bundle.js', 26 | 'swagger-ui-standalone-preset.js', 27 | ]; 28 | 29 | public $css = [ 30 | 'swagger-ui.css' 31 | ]; 32 | 33 | public $depends = []; 34 | } 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "light/yii2-swagger", 3 | "description": "swagger intergation with yii2", 4 | "type": "library", 5 | "keywords": ["yii2","extension","swagger","Restful","document"], 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "lichunqiang", 10 | "email": "light-li@hotmail.com" 11 | } 12 | ], 13 | "require": { 14 | "yiisoft/yii2": "^2.0.0", 15 | "zircote/swagger-php": "^5.0", 16 | "bower-asset/swagger-ui": "^5.0" 17 | }, 18 | "minimum-stability": "stable", 19 | "autoload": { 20 | "psr-4": { 21 | "light\\swagger\\": "src" 22 | } 23 | }, 24 | "extra": { 25 | "branch-alias": { 26 | "dev-master": "2.0.x-dev" 27 | } 28 | }, 29 | "config": { 30 | "process-timeout": 1800, 31 | "fxp-asset": { 32 | "enabled": false 33 | } 34 | }, 35 | "repositories": [ 36 | { 37 | "type": "composer", 38 | "url": "https://asset-packagist.org" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 lichunqiang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

Yii2 Swagger Extension

6 |
7 |

8 | 9 | [![version](https://img.shields.io/packagist/v/light/yii2-swagger.svg?style=flat-square)](https://packagist.org/packages/light/yii2-swagger) 10 | [![Download](https://img.shields.io/packagist/dt/light/yii2-swagger.svg?style=flat-square)](https://packagist.org/packages/light/yii2-swagger) 11 | [![Issues](https://img.shields.io/github/issues/lichunqiang/yii2-swagger.svg?style=flat-square)](https://github.com/lichunqiang/yii2-swagger/issues) 12 | 13 | [swagger-php](https://github.com/zircote/swagger-php) integration with yii2. 14 | 15 | 16 | Integration [swagger-ui](https://github.com/swagger-api/swagger-ui) with [swagger-php](https://github.com/zircote/swagger-php). 17 | 18 | 19 | Installation 20 | ------------ 21 | 22 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 23 | 24 | Either run 25 | 26 | ``` 27 | php composer.phar require --prefer-dist light/yii2-swagger "~3.0" --dev 28 | ``` 29 | 30 | or add 31 | 32 | ``` 33 | "light/yii2-swagger": "~3.0" 34 | ``` 35 | 36 | to the require section of your `composer.json` file. 37 | 38 | 39 | Usage 40 | ----- 41 | 42 | Configure two action as below: 43 | 44 | ``` 45 | public function actions() 46 | { 47 | return [ 48 | //The document preview addesss:http://api.yourhost.com/site/doc 49 | 'doc' => [ 50 | 'class' => 'light\swagger\SwaggerAction', 51 | 'restUrl' => \yii\helpers\Url::to(['/site/api'], true), 52 | ], 53 | //The resultUrl action. 54 | 'api' => [ 55 | 'class' => 'light\swagger\SwaggerApiAction', 56 | //The scan directories, you should use real path there. 57 | 'scanDir' => [ 58 | Yii::getAlias('@api/modules/v1/swagger'), 59 | Yii::getAlias('@api/modules/v1/controllers'), 60 | Yii::getAlias('@api/modules/v1/models'), 61 | Yii::getAlias('@api/models'), 62 | ], 63 | //The security key 64 | 'api_key' => 'balbalbal', 65 | ], 66 | ]; 67 | } 68 | ``` 69 | 70 | > For security, you can config api key for protection. 71 | 72 | Caching 73 | ------- 74 | 75 | ``` 76 | public function actions() 77 | { 78 | return [ 79 | // ... 80 | 'api' => [ 81 | // ... 82 | 'cache' => 'cache', 83 | 'cacheKey' => 'api-swagger-cache', // default is 'api-swagger-cache' 84 | ], 85 | ]; 86 | } 87 | ``` 88 | 89 | #### Clear cache 90 | 91 | Access clear cache url `YOUR_API_URL?clear-cache` or `YOUR_API_URL?api_key=YOUR_API_KEY&clear-cache` 92 | 93 | Example: `curl 'http://localhost/v1/swagger/api?clear-cache'` 94 | 95 | you will see: `Succeed clear swagger api cache.` 96 | 97 | 98 | Finally 99 | ---- 100 | __If there also some confused, you can refer the [Demo](https://github.com/lichunqiang/yii2-swagger-demo).__ 101 | 102 | 103 | License 104 | ------- 105 | ![MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square) 106 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

Yii2 Swagger Extension

6 |
7 |

8 | 9 | [![version](https://img.shields.io/packagist/v/light/yii2-swagger.svg?style=flat-square)](https://packagist.org/packages/light/yii2-swagger) 10 | [![Download](https://img.shields.io/packagist/dt/light/yii2-swagger.svg?style=flat-square)](https://packagist.org/packages/light/yii2-swagger) 11 | [![Issues](https://img.shields.io/github/issues/lichunqiang/yii2-swagger.svg?style=flat-square)](https://github.com/lichunqiang/yii2-swagger/issues) 12 | 13 | [swagger-php](https://github.com/zircote/swagger-php) intergation with yii2. 14 | 15 | 写在前面 16 | -------- 17 | 18 | * 这玩意是干什么的呢? 19 | 20 | 没啥黑科技,只是集成了[swagger-ui](https://github.com/swagger-api/swagger-ui)然后配合[swagger-php](https://github.com/zircote/swagger-php)扫描你的代码目录来生成在Restful文档. 21 | 22 | 23 | Installation 24 | ------------ 25 | 26 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 27 | 28 | Either run 29 | 30 | ``` 31 | php composer.phar require --prefer-dist light/yii2-swagger "~1.0.0" --dev 32 | ``` 33 | 34 | or add 35 | 36 | ``` 37 | "light/yii2-swagger": "~1.0.0" 38 | ``` 39 | 40 | to the require section of your `composer.json` file. 41 | 42 | 43 | Usage 44 | ----- 45 | 46 | 只要配置两个Action就可以了: 47 | 48 | ``` 49 | public function actions() 50 | { 51 | return [ 52 | //文档预览地址,配置好后可以直接访问:http://api.yourhost.com/site/doc 53 | 'doc' => [ 54 | 'class' => 'light\swagger\SwaggerAction', 55 | 'restUrl' => \yii\helpers\Url::to(['/site/api'], true), 56 | ], 57 | //看到上面配置的*restUrl*了么,没错, 它就是指向这个地址 58 | 'api' => [ 59 | 'class' => 'light\swagger\SwaggerApiAction', 60 | //这里配置需要扫描的目录,不支持yii的alias,所以需要这里直接获取到真实地址 61 | 'scanDir' => [ 62 | Yii::getAlias('@api/modules/v1/swagger'), 63 | Yii::getAlias('@api/modules/v1/controllers'), 64 | Yii::getAlias('@api/modules/v1/models'), 65 | Yii::getAlias('@api/models'), 66 | ], 67 | //这个下面讲 68 | 'api_key' => 'balbalbal', 69 | ], 70 | ]; 71 | } 72 | ``` 73 | 74 | `api_key` 是文档浏览key,文档放到线上,我们并不需要让每个人都能看到,所以可以通过设置这项来实现。配置后浏览文档时需要在右上角的`api_key`输入框中输入配置的值,才能正常访问文档. 75 | 76 | > 默认情况下,没有配置的话,可以直接浏览文档 77 | 78 | 79 | **靠!写了这么多我自己都乱了!怎么用??** 80 | 81 | 别担心, **Talk is cheap, show me the code**. 82 | 83 | 84 | 上[Demo](https://github.com/lichunqiang/yii2-swagger-demo) 85 | 86 | 87 | Caching 88 | ------- 89 | 90 | ``` 91 | public function actions() 92 | { 93 | return [ 94 | // ... 95 | 'api' => [ 96 | // ... 97 | 'cache' => 'cache', 98 | 'cacheKey' => 'api-swagger-cache', // default is 'api-swagger-cache' 99 | ], 100 | ]; 101 | } 102 | ``` 103 | 104 | #### Clear cache 105 | 106 | Access clear cache url `YOUR_API_URL?clear-cache` or `YOUR_API_URL?api_key=YOUR_API_KEY&clear-cache` 107 | 108 | Example: `curl 'http://localhost/v1/swagger/api?clear-cache'` 109 | 110 | you will see: `Succeed clear swagger api cache.` 111 | 112 | License 113 | ------- 114 | ![MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square) 115 | -------------------------------------------------------------------------------- /src/index.php: -------------------------------------------------------------------------------- 1 | 14 | beginPage() ?> 15 | 16 | 17 | 18 | 19 | <?= $title ?> 20 | 21 | 22 | 23 | 42 | head() ?> 43 | 44 | 45 | 46 | beginBody() ?> 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
82 | endBody() ?> 83 | registerJs(<< 94 | 95 | 96 | 97 | endPage() ?> 98 | -------------------------------------------------------------------------------- /src/SwaggerApiAction.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace light\swagger; 13 | 14 | use OpenApi\Generator; 15 | use OpenApi\Util; 16 | use Symfony\Component\Finder\Finder; 17 | use Yii; 18 | use yii\base\Action; 19 | use yii\base\ExitException; 20 | use yii\base\InvalidConfigException; 21 | use yii\caching\Cache; 22 | use yii\caching\CacheInterface; 23 | use yii\di\Instance; 24 | use yii\helpers\ArrayHelper; 25 | use yii\web\Response; 26 | 27 | /** 28 | * The api data output action. 29 | * 30 | * ~~~ 31 | * public function actions() 32 | * { 33 | * return [ 34 | * 'api' => [ 35 | * 'class' => 'light\swagger\SwaggerApiAction', 36 | * 'scanDir' => [ 37 | * Yii::getAlias('@api/modules/v1/swagger'), 38 | * Yii::getAlias('@api/modules/v1/controllers'), 39 | * ... 40 | * ] 41 | * ] 42 | * ]; 43 | * } 44 | * ~~~ 45 | */ 46 | class SwaggerApiAction extends Action 47 | { 48 | /** 49 | * @var string|array|Finder The directory(s) or filename(s). 50 | * If you configured the directory must be full path of the directory. 51 | */ 52 | public $scanDir; 53 | /** 54 | * @var string api key, if configured will perform the authentication. 55 | * @deprecated 56 | */ 57 | public $api_key; 58 | /** 59 | * @var string The `apiKey` name specified. 60 | */ 61 | public $apiKeyParam = 'api_key'; 62 | /** 63 | * @var array The options passed to `Swagger`, Please refer the `Swagger\scan` function for more information. 64 | */ 65 | public $scanOptions = []; 66 | /** 67 | * @var Cache|string|null the cache object or the ID of the cache application component that is used to store 68 | * Cache the \Swagger\Scan 69 | */ 70 | public $cache = 'cache'; 71 | /** 72 | * @var bool If enable caching the scan result. 73 | * @since 2.0.0 74 | */ 75 | public $enableCache = false; 76 | /** 77 | * @var string Cache key 78 | * [[cache]] must not be null 79 | */ 80 | public $cacheKey = 'api-swagger-cache'; 81 | 82 | /** 83 | * @throws InvalidConfigException 84 | */ 85 | public function init() 86 | { 87 | $this->cache = Instance::ensure($this->cache, CacheInterface::class); 88 | 89 | $this->initCors(); 90 | } 91 | 92 | /** 93 | * @inheritdoc 94 | * 95 | * @throws ExitException 96 | * @throws InvalidConfigException 97 | */ 98 | public function run() 99 | { 100 | Yii::$app->response->format = Response::FORMAT_JSON; 101 | 102 | $this->clearCache(); 103 | 104 | if ($this->enableCache) { 105 | if (($swagger = $this->cache->get($this->cacheKey)) === false) { 106 | $swagger = $this->getSwagger(); 107 | $this->cache->set($this->cacheKey, $swagger); 108 | } 109 | } else { 110 | $swagger = $this->getSwagger(); 111 | } 112 | 113 | return $swagger; 114 | } 115 | 116 | /** 117 | * Init cors. 118 | */ 119 | protected function initCors() 120 | { 121 | $headers = Yii::$app->getResponse()->getHeaders(); 122 | 123 | $headers->set('Access-Control-Allow-Headers', implode(', ', [ 124 | 'Content-Type', 125 | $this->apiKeyParam, 126 | 'Authorization', 127 | ])); 128 | $headers->set('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT'); 129 | $headers->set('Access-Control-Allow-Origin', '*'); 130 | } 131 | 132 | /** 133 | * 134 | * @throws ExitException 135 | */ 136 | protected function clearCache() 137 | { 138 | $clearCache = Yii::$app->getRequest()->get('clear-cache', false); 139 | if ($clearCache !== false) { 140 | $this->cache->delete($this->cacheKey); 141 | 142 | Yii::$app->response->content = 'Succeed clear swagger api cache.'; 143 | Yii::$app->end(); 144 | } 145 | } 146 | 147 | /** 148 | * Get swagger object 149 | * 150 | * @return OpenApi 151 | */ 152 | protected function getSwagger() 153 | { 154 | $exclude = ArrayHelper::getValue($this->scanOptions, 'exclude'); 155 | $pattern = ArrayHelper::getValue($this->scanOptions, 'pattern'); 156 | return Generator::scan(Util::finder($this->scanDir, $exclude, $pattern), $this->scanOptions); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/SwaggerAction.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace light\swagger; 13 | 14 | use Yii; 15 | use yii\base\Action; 16 | use yii\base\InvalidArgumentException; 17 | use yii\helpers\Json; 18 | use yii\web\JsExpression; 19 | use yii\web\Response; 20 | 21 | /** 22 | * The document display action. 23 | * 24 | * To use url property 25 | * ~~~ 26 | * public function actions() 27 | * { 28 | * return [ 29 | * 'doc' => [ 30 | * 'class' => 'light\swagger\SwaggerAction', 31 | * 'restUrl' => Url::to(['site/api'], true) 32 | * 'additionalAsset' => 'app\modules\api\assets\SwaggerUIAssetOverrides', 33 | * ] 34 | * ]; 35 | * } 36 | * 37 | * To use urls property 38 | * 39 | * public function actions() 40 | * { 41 | * return [ 42 | * 'doc' => [ 43 | * 'class' => 'light\swagger\SwaggerAction', 44 | * 'restUrl' => [ 45 | * [ 46 | * 'name' => 'API V1', 47 | * 'url' => Url::to(['/site/api-v1'], true), 48 | * ], 49 | * [ 50 | * 'name' => 'API V2', 51 | * 'url' => Url::to(['/site/api-v2'], true), 52 | * ], 53 | * ], 54 | * 'additionalAsset' => 'app\modules\api\assets\SwaggerUIAssetOverrides', 55 | * ] 56 | * ]; 57 | * } 58 | * ~~~ 59 | */ 60 | class SwaggerAction extends Action 61 | { 62 | /** 63 | * @var string|array The rest url configuration. 64 | * Check documentation for more information. 65 | * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md 66 | */ 67 | public $restUrl; 68 | /** 69 | * @var array The OAuth configuration. 70 | */ 71 | public $oauthConfiguration = []; 72 | /** 73 | * @var string The customer asset bundle. 74 | * @since 2.0.0 75 | */ 76 | public $additionalAsset; 77 | /** 78 | * @var string 79 | * @since 2.0.0 80 | */ 81 | public $title = 'Swagger-ui'; 82 | /** 83 | * @var array The swagger-ui component configurations. 84 | * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md 85 | * @since 2.0.0 86 | */ 87 | public $configurations = []; 88 | /** 89 | * @var array Default swagger-ui configurations. 90 | * @since 2.0.0 91 | */ 92 | protected $defaultConfigurations = [ 93 | 'dom_id' => '#swagger-ui', 94 | 'deepLinking' => true, 95 | 'presets' => [ 96 | 'SwaggerUIBundle.presets.apis', 97 | 'SwaggerUIStandalonePreset', 98 | ], 99 | 'plugins' => [ 100 | 'SwaggerUIBundle.plugins.DownloadUrl', 101 | 'SwaggerUIBundle.plugins.Topbar', 102 | ], 103 | 'layout' => 'StandaloneLayout', 104 | 'validatorUrl' => null, 105 | ]; 106 | 107 | /** 108 | * @inheritdoc 109 | */ 110 | public function run() 111 | { 112 | Yii::$app->getResponse()->format = Response::FORMAT_HTML; 113 | 114 | $this->controller->layout = false; 115 | 116 | $view = $this->controller->getView(); 117 | 118 | return $view->renderFile(__DIR__ . '/index.php', [ 119 | 'configurations' => $this->prepareConfiguration(), 120 | 'oauthConfiguration' => $this->oauthConfiguration, 121 | 'title' => $this->title, 122 | ], $this->controller); 123 | } 124 | 125 | /** 126 | * @return string 127 | */ 128 | protected function prepareConfiguration() 129 | { 130 | $configurations = array_merge($this->defaultConfigurations, $this->configurations); 131 | 132 | if ($this->restUrl) { 133 | $configurations[is_array($this->restUrl) ? 'urls' : 'url'] = $this->restUrl; 134 | } 135 | 136 | if (isset($configurations['plugins'])) { 137 | $configurations['plugins'] = array_map( 138 | [$this, 'convertJsExpression'], 139 | (array)$configurations['plugins'] 140 | ); 141 | } 142 | 143 | if (isset($configurations['presets'])) { 144 | $configurations['presets'] = array_map( 145 | [$this, 'convertJsExpression'], 146 | (array)$configurations['presets'] 147 | ); 148 | } 149 | 150 | return Json::encode($configurations); 151 | } 152 | 153 | /** 154 | * @param string $str 155 | * 156 | * @return JsExpression 157 | */ 158 | protected function convertJsExpression($str) 159 | { 160 | return new JsExpression($str); 161 | } 162 | 163 | /** 164 | * @inheritdoc 165 | */ 166 | protected function beforeRun() 167 | { 168 | if ($this->additionalAsset != null) { 169 | $additionalAsset = $this->additionalAsset; 170 | if (class_exists($additionalAsset) and method_exists($additionalAsset, 'register')) { 171 | $additionalAsset::register($this->controller->getView()); 172 | } else { 173 | throw new InvalidArgumentException('Not valid class'); 174 | } 175 | } 176 | 177 | return parent::beforeRun(); 178 | } 179 | } 180 | --------------------------------------------------------------------------------