├── .gitignore ├── config └── postman.php ├── src ├── LaravelPostmanServiceProvider.php ├── Helper.php └── LaravelPostmanCommand.php ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.lock 3 | -------------------------------------------------------------------------------- /config/postman.php: -------------------------------------------------------------------------------- 1 | '', 5 | 'collectionName' => '', 6 | 'collectionDescription' => '', 7 | 'apiPrefix' => 'api', 8 | 'skipHEAD' => true, 9 | 'exportDirectory' => '', 10 | ]; -------------------------------------------------------------------------------- /src/LaravelPostmanServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton('JimenezMaximiliano\LaravelPostman\Helper', function($app) 28 | { 29 | return new Helper(); 30 | }); 31 | 32 | $this->commands('JimenezMaximiliano\LaravelPostman\LaravelPostmanCommand'); 33 | 34 | $configFilePath = __DIR__ . '/../config/laravelPostman.php'; 35 | $this->publishes([ 36 | $configFilePath => config_path('laravelPostman.php'), 37 | ]); 38 | } 39 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jimenezmaximiliano/laravel-postman", 3 | "type": "library", 4 | "description": "Export laravel API routes to postman", 5 | "keywords": [ 6 | "jimenezmaximiliano", 7 | "laravel", 8 | "postman", 9 | "github", 10 | "export", 11 | "api" 12 | ], 13 | "homepage": "https://github.com/jimenezmaximiliano/laravel-postman", 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "Maximiliano Jimenez", 18 | "email": "jimenez@maximiliano.com.ar", 19 | "homepage": "http://maximiliano.com.ar", 20 | "role": "Developer" 21 | } 22 | ], 23 | "require": { 24 | "illuminate/support": "~5", 25 | "illuminate/console": "~5", 26 | "php" : ">=5.4" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit" : "~4.0||~5.0" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "JimenezMaximiliano\\LaravelPostman\\": "src" 34 | } 35 | }, 36 | "scripts": { 37 | "test": "phpunit", 38 | "format": "phpcbf --standard=psr2 src/" 39 | }, 40 | "extra": { 41 | "branch-alias": { 42 | "dev-master": "1.0-dev" 43 | } 44 | }, 45 | "config": { 46 | "sort-packages": true 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-postman 2 | This package allows you to export your API routes to a postman import json file 3 | 4 | ## Installation 5 | 6 | Install the package via composer 7 | 8 | `composer require --dev jimenezmaximiliano/laravel-postman` 9 | 10 | Then add the service provider in config/app.php: 11 | 12 | ### PHP >= 5.5 13 | 14 | `JimenezMaximiliano\LaravelPostman\LaravelPostmanServiceProvider::class` 15 | 16 | ### PHP < 5.5 17 | 18 | `JimenezMaximiliano\LaravelPostman\LaravelPostmanServiceProvider` 19 | 20 | ## Configuration 21 | 22 | First, publish the package configuration file: 23 | 24 | `php artisan vendor:publish` 25 | 26 | Note: publishing the configuration file is optional, you can use de default package options. 27 | 28 | ### Options 29 | 30 | #### apiURL 31 | This is the base URL for your postman routes 32 | 33 | default value: config('app.url') 34 | 35 | #### collectionName 36 | This is the postman collection name 37 | 38 | default value: the command will ask for it 39 | 40 | #### collectionDescription 41 | This is the postman collection description 42 | 43 | default value: the command will ask for it 44 | 45 | #### apiPrefix 46 | This is the prefix by which we identify the routes to export 47 | 48 | default value: 'api' 49 | 50 | #### skipHEAD 51 | This avoids creating routes for HEAD method 52 | 53 | default value: true 54 | 55 | #### exportDirectory 56 | The directory to which the postman.json file will be exported 57 | 58 | ## Usage 59 | 60 | ### Configuring controllers 61 | 62 | Add a property to your entity controller like this: 63 | 64 | `public $postmanModel = 'App\MyEntityModel';` 65 | 66 | ### Add a public method to your model class like this: 67 | 68 | ` 69 | public function getPostmanParams() 70 | { 71 | return $this->fillable; 72 | } 73 | ` 74 | 75 | This array of params will be used to fill POST and PUT urlencoded form data section in 76 | postman. The previous method is just an example, you should return the array of 77 | params that you want to see in postman. 78 | 79 | ### Export 80 | 81 | `php artisan laravelPostman:export` -------------------------------------------------------------------------------- /src/Helper.php: -------------------------------------------------------------------------------- 1 | addTrailingSlash($configURL); 51 | } 52 | 53 | return $this->addTrailingSlash(config('app.url')); 54 | } 55 | 56 | /** 57 | * Returns the API prefix string 58 | * 59 | * @return string 60 | */ 61 | public function getApiPrefix() 62 | { 63 | $apiPrefix = config('postman.apiPrefix'); 64 | 65 | return !empty($apiPrefix) ? $apiPrefix : 'api'; 66 | } 67 | 68 | /** 69 | * Returns a postman collection structure array 70 | * 71 | * @param string $collectionName 72 | * @param string $collectionDescription 73 | * @return array 74 | */ 75 | public function getCollectionStructure( 76 | $collectionName, 77 | $collectionDescription) 78 | { 79 | return [ 80 | 'variables' => [], 81 | 'info' => [ 82 | 'name' => $collectionName, 83 | '_postman_id' => uniqid(), 84 | 'description' => $collectionDescription, 85 | 'schema' => self::POSTMAN_SCHEMA, 86 | ], 87 | 'item' => [], 88 | ]; 89 | } 90 | 91 | /** 92 | * Obtains a postman folder name from the given laravel route 93 | * 94 | * @param Illuminate\Routing\Route $route 95 | * @return string 96 | */ 97 | public function getRouteFolder($route) 98 | { 99 | $actionStringParts = explode('@', $route->getActionName()); 100 | 101 | if (count($actionStringParts) === 1) { 102 | 103 | return 'Others'; 104 | } 105 | 106 | $fullController = $actionStringParts[self::CONTROLLER_STRING_INDEX]; 107 | $controllerClass = explode('\\', $fullController); 108 | 109 | return str_replace('Controller', '', last($controllerClass)); 110 | } 111 | 112 | /** 113 | * Returns the path where the exported file will be located 114 | * 115 | * @return string 116 | */ 117 | public function getExportDirectory() 118 | { 119 | $exportDirectory = config('postman.exportDirectory'); 120 | 121 | if (empty($exportDirectory)) { 122 | 123 | return $exportDirectory; 124 | } 125 | 126 | return $this->addTrailingSlash($exportDirectory); 127 | } 128 | 129 | /** 130 | * Finds out if a postman model can be get from the route 131 | * 132 | * @param Illuminate\Routing\Route $route 133 | * @return boolean 134 | */ 135 | public function canGetPostmanModel($route) 136 | { 137 | if (method_exists($route, 'getController') 138 | && is_object($route->getController()) 139 | && property_exists($route->getController(), 'postmanModel')) { 140 | 141 | return true; 142 | } 143 | 144 | if (method_exists($route, 'getAction') 145 | && is_array($route->getAction()) 146 | && in_array('controller', array_keys($route->getAction()))) { 147 | 148 | return true; 149 | } 150 | 151 | return false; 152 | } 153 | 154 | /** 155 | * Returns a route's postman model 156 | * 157 | * @param Illuminate\Routing\Route $route 158 | * @return object|null 159 | */ 160 | public function getPostmanModel($route) 161 | { 162 | if (!$this->canGetPostmanModel($route)) { 163 | 164 | return null; 165 | } 166 | 167 | if (method_exists($route, 'getController')) { 168 | 169 | $postmanModelClass = $route->getController()->postmanModel; 170 | } 171 | 172 | $action = $route->getAction(); 173 | $controllerAction = explode('@', $action['controller']); 174 | $controllerClass = $controllerAction[0]; 175 | $controller = app($controllerClass); 176 | 177 | if (!property_exists($controller, 'postmanModel')) { 178 | 179 | return null; 180 | } 181 | 182 | $postmanModelClass = $controller->postmanModel; 183 | 184 | return new $postmanModelClass(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/LaravelPostmanCommand.php: -------------------------------------------------------------------------------- 1 | helper = $helper; 35 | parent::__construct(); 36 | } 37 | 38 | /** 39 | * Execute the console command. 40 | * 41 | * @return void 42 | */ 43 | public function handle() 44 | { 45 | $collectionName = $this->getCollectionName(); 46 | $collectionDescription = $this->getCollectionDescription(); 47 | $collection = $this->helper->getCollectionStructure( 48 | $collectionName, 49 | $collectionDescription); 50 | 51 | foreach ($this->getRoutes() as $folderName => $folderRoutes) { 52 | 53 | $items = []; 54 | foreach ($folderRoutes as $route) { 55 | 56 | $items = array_merge($this->getRouteItems($route), $items); 57 | } 58 | 59 | $collection['item'][] = [ 60 | 'name' => $folderName, 61 | 'description' => '', 62 | 'item' => $items, 63 | ]; 64 | } 65 | 66 | file_put_contents( 67 | $this->helper->getExportDirectory() . 'postman.json', 68 | json_encode($collection)); 69 | } 70 | 71 | /** 72 | * Returns an array of route items (route + method) for the given route 73 | * 74 | * @param Illuminate\Routing\Route $route 75 | * @return array 76 | */ 77 | protected function getRouteItems($route) 78 | { 79 | $baseURL = $this->helper->getBaseURL(); 80 | $path = $this->helper->replaceGetParameters($route->uri()); 81 | $routeName = $route->getName(); 82 | $routeNameFinal = !empty($routeName) ? $routeName : $path; 83 | $methods = $route->methods(); 84 | $items = []; 85 | 86 | foreach ($methods as $method) { 87 | 88 | if ($method === 'HEAD' && config('postman.skipHEAD', true)) { 89 | 90 | continue; 91 | } 92 | $body = $this->getBody($route, $method); 93 | $items[] = $this->getItemStructure( 94 | $routeNameFinal, 95 | $baseURL, 96 | $path, 97 | $method, 98 | $body); 99 | } 100 | 101 | return $items; 102 | } 103 | 104 | /** 105 | * Returns an array with postman item format 106 | * 107 | * @param string $routeName 108 | * @param string $baseURL 109 | * @param string $path 110 | * @param string $method 111 | * @param string $body 112 | * @return string 113 | */ 114 | protected function getItemStructure( 115 | $routeName, 116 | $baseURL, 117 | $path, 118 | $method, 119 | $body) 120 | { 121 | return [ 122 | 'name' => $routeName, 123 | 'request' => [ 124 | 'url' => $baseURL . $path, 125 | 'method' => $method, 126 | 'body' => $body, 127 | ], 128 | 'response' => [], 129 | ]; 130 | } 131 | 132 | /** 133 | * Returns the user's collection name 134 | * 135 | * @return string 136 | */ 137 | protected function getCollectionName() 138 | { 139 | $configCollectionName = config('postman.collectionName'); 140 | 141 | if (!empty($configCollectionName)) { 142 | 143 | return $configCollectionName; 144 | } 145 | 146 | return $this->ask('Enter collection name', 'LaravelPostman Collection'); 147 | } 148 | 149 | /** 150 | * Returns the user's collection description 151 | * 152 | * @return string 153 | */ 154 | protected function getCollectionDescription() 155 | { 156 | $configCollectionDescription = config('postman.collectionDescription'); 157 | 158 | if (!empty($configCollectionDescription)) { 159 | 160 | return $configCollectionDescription; 161 | } 162 | 163 | return $this->ask('Enter collection description', 164 | 'Postman collection generated by LaravelPostman'); 165 | } 166 | 167 | /** 168 | * Returns an array of API routes organized by folders 169 | * 170 | * @return array 171 | */ 172 | protected function getRoutes() 173 | { 174 | $resultRoutes = []; 175 | $apiPrefix = $this->helper->getApiPrefix(); 176 | $apiPrefixLength = strlen($apiPrefix); 177 | 178 | foreach (Route::getRoutes() as $route) { 179 | 180 | $path = $route->uri(); 181 | if (substr($path, 0, $apiPrefixLength) !== $apiPrefix) { 182 | $this->info('Omiting ' . $path); 183 | 184 | continue; 185 | } 186 | 187 | $routeFolder = $this->helper->getRouteFolder($route); 188 | if (!isset($resultRoutes[$routeFolder])) { 189 | $resultRoutes[$routeFolder] = []; 190 | } 191 | 192 | $resultRoutes[$routeFolder][] = $route; 193 | } 194 | 195 | return $resultRoutes; 196 | } 197 | 198 | /** 199 | * Returns an postman body array for the given route 200 | * 201 | * @param Illuminate\Routing\Route $route 202 | * @param string $method 203 | * @return array 204 | */ 205 | protected function getBody($route, $method) { 206 | 207 | $postmanParams = $this->getRouteParams($route, $method); 208 | 209 | if (empty($postmanParams)) { 210 | return []; 211 | } 212 | 213 | $body['mode'] = 'urlencoded'; 214 | $body['urlencoded'] = []; 215 | foreach ($postmanParams as $param) { 216 | $body['urlencoded'][] = [ 217 | 'key' => $param, 218 | 'value' => '', 219 | 'enabled' => true, 220 | ]; 221 | } 222 | 223 | return $body; 224 | } 225 | 226 | /** 227 | * Returns an array of the given route parameters 228 | * 229 | * @param Illuminate\Routing\Route $route 230 | * @param string $method 231 | * @return array 232 | */ 233 | protected function getRouteParams($route, $method) 234 | { 235 | if ($method === 'GET' || $method === 'DELETE') { 236 | return []; 237 | } 238 | 239 | if (!$this->helper->canGetPostmanModel($route)) { 240 | 241 | return []; 242 | } 243 | 244 | $postmanModel = $this->helper->getPostmanModel($route); 245 | 246 | if (!is_object($postmanModel) 247 | || !method_exists($postmanModel, 'getPostmanParams')) { 248 | 249 | return []; 250 | } 251 | 252 | return $postmanModel->getPostmanParams(); 253 | } 254 | } 255 | --------------------------------------------------------------------------------