|
1 | 1 | # php-api-client-forge |
2 | | -Create restful API client in PHP with least code |
3 | 2 |
|
| 3 | +Create restful API client from Postman Collection data (or other sources) in PHP with least code. |
| 4 | +# php-api-client-forge |
| 5 | + |
| 6 | +- Create restful API client class from Postman Collection data (or other sources) |
| 7 | +- Auto generate class `@method` documentation for phpDoc |
| 8 | +- Auto generate Markdown API Documentation |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | +[](https://packagist.org/packages/sudiptochoudhury/php-api-client-forge) |
| 13 | +[](//packagist.org/packages/sudiptochoudhury/php-api-client-forge) |
| 14 | +[](https://packagist.org/packages/sudiptochoudhury/php-api-client-forge) |
| 15 | +[](https://packagist.org/packages/sudiptochoudhury/php-api-client-forge) |
| 16 | +[](https://packagist.org/packages/sudiptochoudhury/php-api-client-forge) |
| 17 | + |
| 18 | +Import API definitions from Postman exported JSON to a JSON compatible with Guzzle\Description format |
| 19 | +or pass a `GuzzleHttp\Command\Guzzle\Description` object and |
| 20 | +your API class is ready to roll. |
| 21 | + |
| 22 | +> As a bonus, you will also get an auto generated API documentation in markdown format. Moreover, you will get a php |
| 23 | +file with `@method` declarations for phpDoc class documentation. |
| 24 | + |
| 25 | +This package needs to be used as parent. Extend the `Client` class to make you own API class. |
| 26 | + |
| 27 | +> This is specially |
| 28 | +designed to import Postman collection exported as JSON (Collection v2.1 - |
| 29 | +[Schema](https://schema.getpostman.com/json/collection/v2.1.0/collection.json)). |
| 30 | + |
| 31 | + |
| 32 | +<a name="basics"/> |
| 33 | + |
| 34 | +## Basics |
| 35 | + |
| 36 | +```php |
| 37 | + |
| 38 | +<?php |
| 39 | + |
| 40 | +namespace My\Namespace\ApiProvider; |
| 41 | + |
| 42 | +use SudiptoChoudhury\Support\Forge\Api\Client as ApiForge; |
| 43 | + |
| 44 | +class Api extends ApiForge |
| 45 | +{ |
| 46 | + |
| 47 | + protected $DEFAULT_API_JSON_PATH = './config/GuzzleDescription.json'; |
| 48 | + |
| 49 | + protected $DEFAULTS = [ |
| 50 | + 'AuthToken' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx', |
| 51 | + 'ClientID' => 'xxxxxxxxxxxxxxx', |
| 52 | + 'client' => [ |
| 53 | + 'base_uri' => 'https://api.provider.com/api/v1/', |
| 54 | + 'verify' => false, |
| 55 | + 'headers' => [ |
| 56 | + 'Authorization' => 'Zoho-authtoken {{AuthToken}}', |
| 57 | + 'X-com-zoho-subscriptions-organizationid' => "{{ClientID}}", |
| 58 | + ], |
| 59 | + ], |
| 60 | + ]; |
| 61 | + |
| 62 | +} |
| 63 | + |
| 64 | +``` |
| 65 | +That should be it. Nothing else is required. All the API endpoint will be intelligently converted to functions of this |
| 66 | +class. For example, if you have an endpoint `[GET]/products`, you will get a `getProducts` function. Here are some more |
| 67 | +examples: |
| 68 | + |
| 69 | +| HTTP Method | Endpoint | Converted function name | Parameters | Example call | |
| 70 | +|-------------|----------|-------------------------|------------|--------------| |
| 71 | +|GET| /products| `getProducts` | none | `$api->getProducts()`| |
| 72 | +|GET| /products/{product_id}| `getProduct` | `product_id` | `$api->getProduct(['product_id' => 101])`| |
| 73 | +|POST| /products| `addProduct` | a list of params | `$api->addProduct($data)`| |
| 74 | +|PUT| /products/{product_id}| updateProduct | `product_id` and a list of other parameters | `$api->updateProduct(['product_id' => 101])`...| |
| 75 | +|DELETE| /products/{product_id}| deleteProduct | `product_id` | `$api->deleteProduct(['product_id' => 101])`| |
| 76 | + |
| 77 | +Tried best to normalize the singulars and plurals. |
| 78 | + |
| 79 | + |
| 80 | +> There can be cases when the API endpoint structure is same as the another but the data passed to it determines a |
| 81 | +different action altogether. Ideally, this should not happen but not all API enpoints are ideally created. |
| 82 | +So, an endpoint like `[get]/products?filter_by=active` along with another endpoint `[get]/products` will have the |
| 83 | +same name. To keep both, the default behaviour is to add an `_` before the duplicate name. However, you can add filters |
| 84 | +or hooks to completely change the duplicate name to something else. |
| 85 | + |
| 86 | + |
| 87 | +<a name="install"/> |
| 88 | + |
| 89 | +## Installation |
| 90 | + |
| 91 | +<a name="requirements"/> |
| 92 | + |
| 93 | +### Requirements |
| 94 | + |
| 95 | +- Any flavour of PHP 7.0+ should do |
| 96 | + |
| 97 | +<a name="install-composer"/> |
| 98 | + |
| 99 | +### Install With Composer |
| 100 | + |
| 101 | +You can install the library via [Composer](http://getcomposer.org) by adding the following line to the |
| 102 | +**require** block of your *composer.json* file (replace dev-master with latest stable version): |
| 103 | + |
| 104 | +``` |
| 105 | +"sudiptochoudhury/php-api-client-forge": "dev-master" |
| 106 | +``` |
| 107 | + |
| 108 | +or run the following command: |
| 109 | + |
| 110 | +``` |
| 111 | +composer require sudiptochoudhury/php-api-client-forge |
| 112 | +``` |
| 113 | + |
| 114 | +<a name="import"/> |
| 115 | + |
| 116 | +## Importing Postman JSON |
| 117 | + |
| 118 | +Export your Postman Collection using COllecton v2.1 format. It will be exported as JSON. Give the file a |
| 119 | +name, say `postman.json` and keep it inside a folder in your project. |
| 120 | + |
| 121 | +Next, extend `Import` class (recommended) or may use it directly. |
| 122 | + |
| 123 | +#### By Extending the `Import` class |
| 124 | + |
| 125 | +```php |
| 126 | +<?php |
| 127 | +namespace My\Namespace\ApiProvider; |
| 128 | + |
| 129 | +use SudiptoChoudhury\Support\Forge\Api\Import as ParentImport; |
| 130 | + |
| 131 | +/** |
| 132 | + * Class Import |
| 133 | + * |
| 134 | + * @package Pour\Package\Name |
| 135 | + */ |
| 136 | +class Import extends ParentImport |
| 137 | +{ |
| 138 | + |
| 139 | + protected $DEFAULT_API_JSON_PATH = './config/GuzzleDescription.json'; |
| 140 | + protected $DEFAULT_SOURCE_JSON_PATH = './config/postman.json'; |
| 141 | + |
| 142 | +} |
| 143 | +``` |
| 144 | +You are ready to import. That's pretty much it (though there are tons of configurable options and hooks... |
| 145 | + we will come to that soon). |
| 146 | + |
| 147 | +Now, let's import in some other part of your codebase. |
| 148 | + |
| 149 | +```php |
| 150 | +<?php |
| 151 | + |
| 152 | +use My\Namespace\ApiProvider\Import; |
| 153 | +... |
| 154 | +new (Import())->writeDefinition(); |
| 155 | +... |
| 156 | + |
| 157 | +``` |
| 158 | + |
| 159 | +Done! |
| 160 | + |
| 161 | + |
| 162 | +#### Directly using parent class |
| 163 | + |
| 164 | +It's even simpler (though) |
| 165 | + |
| 166 | +```php |
| 167 | +<?php |
| 168 | + |
| 169 | +use SudiptoChoudhury\Support\Forge\Api\Import; |
| 170 | + |
| 171 | +... |
| 172 | +new (Import([ |
| 173 | + './config/postman.json' |
| 174 | +]))->writeDefinition( './config/GuzzleDescription.json'); |
| 175 | +... |
| 176 | +``` |
| 177 | + |
| 178 | +Simpler, eh! |
| 179 | + |
| 180 | +You will find a new `.json`, a new `.md` and a new `.php` file to server you well in your API venture forward. |
| 181 | + |
| 182 | +The `.json` file is obviously based on data structure required to create a `GuzzleHttp\Command\Guzzle\Description` |
| 183 | +object. |
| 184 | + |
| 185 | +The `.php` file has phpDoc `@method` definitions and may look something similar to |
| 186 | + |
| 187 | +```php |
| 188 | +<?php |
| 189 | +/** |
| 190 | + * @method array getHostedpage(array $parameters) Getting the details of a particular hosted page |
| 191 | + * @method array getHostedpages() Listing all the hostedpages |
| 192 | + |
| 193 | +``` |
| 194 | + You can copy the method definitions parts to yor API class extended from the `Client` class. |
| 195 | + |
| 196 | + The `.md` file is a markdown file with a table containing details of the API functions, equivalent endpoints, |
| 197 | + parameters, default values for parameters (if defined) and description - all derived from the Postman json file. |
| 198 | + |
| 199 | + |
| 200 | + |
| 201 | +> However, I would recommend to use the extend option as you will get a plethora of options to hook into various |
| 202 | +sections of parent code while the conversion of the Postman data to Guzzle Description is undergoing. |
| 203 | +You may want to add default values or change a name or change description or skip some items. |
| 204 | +All can be done by overriding functions of Import parent class and defining custom filter functions. |
| 205 | + |
| 206 | + |
| 207 | +<a name="filters"/> |
| 208 | + |
| 209 | +## What are custom filter function?!!! |
| 210 | + |
| 211 | +Well, let's pick an example. Let's say you see you want to change the duplicate function name for `[get]/products` as |
| 212 | +I stated an example in previous section. By default, the duplicate name will be set to `_getProducts` |
| 213 | +(remember? by default adding a `_` before the name). |
| 214 | + |
| 215 | +Now, in your extended `Import` class just define this |
| 216 | + |
| 217 | +```php |
| 218 | +<?php |
| 219 | + |
| 220 | + /** This is a filter |
| 221 | + * @param $apiFunctionName |
| 222 | + * @param array $helperData |
| 223 | + * @return string |
| 224 | + */ |
| 225 | + public function filterFinalName($apiFunctionName, $helperData = []) |
| 226 | + { |
| 227 | + if ($apiFunctionName === '_getProducts') { |
| 228 | + $apiFunctionName = 'getActiveProducts'; |
| 229 | + } |
| 230 | + return $apiFunctionName; |
| 231 | + } |
| 232 | + |
| 233 | +``` |
| 234 | + |
| 235 | +This is a filter function. The name must start with `filter` followed by the filter name and can then optionally |
| 236 | +add an `_` and anything you want after that, just in case you want to define multiple functions for the same filter |
| 237 | +(like - `filterFinalName_xxx` or `filterFinalName_001`). |
| 238 | + |
| 239 | +Each filter function will receive the value to be modified in the first parameter. The optional second parameter |
| 240 | +will be an associative array of helper data items that may help in determining logic of how the filter can be applied. |
| 241 | +At times it may also be the source of data to build documentation layouts. For example, the markdown API table is |
| 242 | +generated via a default filter. You can override it to generate the API table in your own way. May be you do not like |
| 243 | +table structure, you may devise you own structure. Sky is the limit. Additionally, there are a lot of filters dedicated |
| 244 | +to create a complete markdown documentation with sections like title, menu, description, table, header, footer, |
| 245 | +install, even donate and contact. Just tap into the desired layout filters and fill in your own content. |
| 246 | + |
| 247 | + |
| 248 | +The table below gives you details of all the filters. |
| 249 | + |
| 250 | +> But before that, you can also do similar things by totally overriding the parent's functions. For example, |
| 251 | +`readApiName` can be overridden to extend or replace existing login to detect a function name with your own logic. |
| 252 | +However, filters help in changing things in a granular way. There can be 10 filters applied to a single |
| 253 | +function you wan to override and you may need to just use one filter out of them instead of writing a big bunch of |
| 254 | +overriding code. Of course, choice is yours. |
4 | 255 |
|
| 256 | +| Filter Name | Description | |
| 257 | +|-------------|------------- | |
| 258 | +| Name | API function name of a single Endpoint | |
| 259 | +| Slug | A slug derived from API's name defined in Postmam | |
| 260 | +| FinalName | API function name after all logic has been applied | |
| 261 | +| Params | Api function parameters | |
| 262 | +| Uri | Endpoint | |
| 263 | +| Operation | Opetaion data of a single endpoint for Guzzle Description | |
| 264 | +| Title | Title of the Postman collection | |
| 265 | +| DocMethodFinalText | phpDoc method as joined text | |
| 266 | +| DocMDItem | Markdown API for single endpoint details as array | |
| 267 | +| DocMDApiExternalLink | Markdown's placeholder for link to external (API service provider's) API Documentation | |
| 268 | +| DocMDEndpoint | Endpoint of API item in Markdown documentation | |
| 269 | +| DocMDDescription | Description of API item in Markdown documentation | |
| 270 | +| DocMDParams | Parameters of API Item Markdown documentation | |
| 271 | +| DocMDParamDefaults | Default values for parameres of API item Markdown documentation | |
| 272 | +| DocMDLayoutTitle | Markdown documentation title | |
| 273 | +| DocMDLayoutSubtitle | Markdown documentation subtitle | |
| 274 | +| DocMDLayoutHeader | Markdown documentation header | |
| 275 | +| DocMDLayoutMenu | Markdown documentation menu | |
| 276 | +| DocMDLayoutDescription | Markdown documentation description | |
| 277 | +| DocMDLayoutRequirements | Markdown documentation requirements section | |
| 278 | +| DocMDLayoutInstall | Markdown documentation install section | |
| 279 | +| DocMDLayoutGetStarted | Markdown documentation gettting started section | |
| 280 | +| DocMDLayoutSetup | Markdown documentation setup section | |
| 281 | +| DocMDLayoutExamples | Markdown documentation examples section | |
| 282 | +| DocMDLayoutTable | Markdown documentation API table section - helper data can be iterated to get data in this structure -`[ 'method' => '\<function name\>', 'endpoint' => '\<endpoint uri\>', 'parameters' => [`\<indexed array\>`], 'defaults' => ['<associative array>'], 'description' => '<api description>']` | |
| 283 | +| DocMDLayoutFooter | Markdown documentation footer section | |
| 284 | +| DocMDLayoutNotes | Markdown documentation notes section | |
| 285 | +| DocMDLayoutReferences | Markdown documentation references section | |
| 286 | +| DocMDLayoutContact | Markdown documentation contact us section | |
| 287 | +| DocMDLayoutDonate | Markdown documentation donate section | |
| 288 | +| DocMDFinalLayoutArray | All Markdown documentation layouts as array | |
| 289 | +| DocMDFinalText | Full Markdown documentation as text | |
| 290 | +| APIDefinitionFinalJson | The full Guzzle Description | |
| 291 | +| DocMethodItem | phpDoc method for single endpoint | |
| 292 | +| DocMethodDescription | Markdown documentation | |
| 293 | +| DocMethodFinalArray | All phpDoc methods as array | |
| 294 | +| DocMethodParams | Parameters for phpDoc | |
| 295 | +| DocMethodData | What needs to shown in the parenthesis of the method signature in phpDoc | |
| 296 | +| DocMethodSignature | Full single method signature for phpDoc | |
| 297 | +| GroupName | Postman Collection's Group Name | |
| 298 | +| GroupDescription | Post Collection's Description | |
5 | 299 |
|
0 commit comments