开发者

Auto documenting REST API in PHP

phpDocumentor seems to be the standard for documenting PHP code, though I have to wonder why it hasn't been updated in years..?

However, it does not seem suitable for documenting the entry points for a REST API; IE, externally accessible entry points that an end user of your system would be interested in, as opposed to documenting all the internal classes and such - something only of interest to the developers 开发者_运维技巧of the api.

I am looking for something where I could say, hey this method here is externally accessible through REST at this URL, here's the GET or POST arguments it takes, it supports GET/POST/etc HTTP methods, it returns JSON or XML or whatever.

This information would be able to produce an API document. It could also be used by the code internally to automatically filter inputs, validate output, create basic unit tests, etc.


I know of 3 PHP integrations with swagger:

  • Swagger PHP composer

  • Swagger PHP Symfony bundle

  • Restler 3.0

All should help auto-create a swagger-spec, which gives you access from swagger-ui. Then you can generate api clients, etc.


A RESTful API should be entirely discoverable and auto-documented. You only need an URL and everything else linked to it should describe itself. Sounds like an utopia, but it's feasible.

For example, let's start out with a stackoverflow-like sample URL: http://restfuloverflow.com (illustrative)

The first thing you do on a RESTful resource is an OPTIONS request. You always need to include an Accept header to instruct the server to respond to the most appropriate mime type:

OPTIONS * HTTP/1.1
Accept: text/html, text/xml, application/json
Host: restfuloverflow.com

The server should instruct the client on what is possible to do on that URL:

HTTP/1.1 200 Ok
Allow: GET, POST, PUT, DELETE, OPTIONS, TRACE, PATCH

This is the RESTful API telling you that this service support these methods. The first one you'll try is something like the request below. An user hitting the API with a browser should work in a similar way.

GET / HTTP/1.1
Accept: text/html, text/xml, application/json
Host: restfuloverflow.com

The server then should return some links pointing to related resources, if available:

HTTP/1.1 200 Ok
Content-Type: text/xml

<?xml version="1.0">
<qa>
    <link href="/questions" title="Questions"/>
    <link href="/tags" title="Tags"/>
    <link href="/users" title="Users"/>
</qa>

An HTML version should use <a> links, and JSON responses should use JSON-Schema links attribute.

Let's say the client now decides that it wants to know what to do with questions:

OPTIONS /questions HTTP/1.1
Host: restfuloverflow.com
Accept: text/html, text/xml, application/json

A possible response could be:

HTTP/1.1 200 Ok
Allow: GET, POST
Content-Type: text/xml

<?xml version="1.0">
<xsd:element name="question">
    <!-- XML Schema describing a question -->
</xsd:element>

Well, the server told us that it's possible to GET and POST a new question. It also told us how a question in XML looks like by providing a XML Schema. A JSON-SCHEMA could be provided for JSON, and in HTML a form for new questions could be provided.

Let's say the user wants to GET questions:

GET /questions HTTP/1.1
Host: restfuloverflow.com
Accept: text/html, text/xml, application/json

Then the server responds:

HTTP/1.1 200 Ok
Content-Type: text/xml

<?xml version="1.0">
<questions>
    <link href="/questions/intersting" title="Intersting Questions"/>
    <link href="/questions/hot" title="Hot Questions"/>
</questions>

Now, everything is linked again. The thing keeps going in a way that the service describes itself. The Netflix API follows similar principles, but lacks some auto-discover features.

This Brazillian Government API describes itself using RDF. It's one of the best RESTful samples I've ever seen. Try changing .rdf to .xml, .json or .html. (It's all in Portuguese, sorry for that).

The best tool for RESTful APIs in PHP is Respect\Rest. It has most of the workflow I've described here already bootstrapped, and new features are coming (It's still in 0.4x version).

The cost of building a documenting system for RESTful applications is the same as building a RESTful application. This is why there are so few tools like that, and usually they're not that good.


I found a great node package named apidoc that does an awesome job at doc-ing RESTfuls. It allows tons of API-specific tags to do with params and things like that, but what really sold me is its generated, in-doc test forms for each method.

I use it in my devops skeleton project at https://github.com/ardkevin84/devops.skel.php-with-docs-metrics, but you can see actual output in my callloop api project at https://github.com/ardkevin84/api.callloop. The apidoc index is build/api-docs/apidoc/index.html

The only downside, if it is one, is that it - naturally - takes its own docblocks. It doesn't clash with 'native' Docblocks, though. The apidoc blocks don't need to precede a method, so I generally group them together at the top of my endpoint file where the other doc engines won't associate them with a class doc.

A byproduct: this works great with facades; I use facade and factory a lot in my endpoints, and the apidoc parser lets me handle the facade conditions separately. In the example below, 'subscribe', 'unsubscribe', and 'trigger' are handled by a single entry-point, but they're documented separately.

Example: This Docblocks

/**
 * @api {get} ?action=:action&first=:firstname&last=:lastname&email=:useremail&phone=:phone&gid=:groupid Subscribe
 * @apiSampleRequest http://www.example.com/rest/callloop.php
 * @apiName Subscribe
 * @apiGroup Subscription
 * @apiDescription subscribes a user to the provided group
 * @apiParam {string="subscribe","unsubscribe","trigger"} action=subscribe API Action to call. For subscriptions, use "subscribe"
 * @apiParam {String} [first] Optional first name
 * @apiParam {String} [last] Optional last name
 * @apiParam {String} [email] Optional user email
 * @apiParam {String} phone User's mobile phone number
 */

is required to generate this output, complete with the test form

Auto documenting REST API in PHP

important, if you are using standard $_GET with query params: The package that's installed from node doesn't support enpoints like service.php?param=value, but there's a pull request in the git repo at https://github.com/apidoc/apidoc/pull/189 which addresses this. It's a basic fix to the default template. I patched the few lines into my node package and it works like a charm.

shameless self-promotion: This is probably much easier to use under an automated build. Check out my devops project above for a kickstart ;) It's forked from jenkins-php, but adds in several doc engines and stub targets for things like pushing generated docs\metrics to a localhost path and packaging output for release (zip, tar, etc)


Swagger seems promising but it will require your API expose itself in a compatible manner... it is quite nice, however, with a test console, etc all built-in... you can download a javascript version and run it on your server alongside the php api.

EDIT: here is the link, it isnt so easy to find on google if you dont have the full name... lol... Swagger-UI: https://github.com/wordnik/swagger-ui


The easiest thing to do is use a docblock tokenizer / parser. There are a couple of them out there (I'll plug mine shortly), but basically they can examine the docblock and tokenize any custom (or non-custom) docblock tags. I've use this inside a framework of mine to define view helper types via a tag called "@helperType".

Like I said, there are plenty out there, but here's mine to get you started: https://github.com/masterexploder/DocumentingReflectionMethod

Basically, use something like that and you can use it to both generate your docs, and to do stuff like auto filtering, validation, etc.

As far as unit test creation, PHPUnit can generate those automatically from your classes (check their docs for more info: http://www.phpunit.de/manual/3.5/en/skeleton-generator.html#skeleton-generator.test

You can also have phpdocumenter parse your custom tags: http://manual.phpdoc.org/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html#using.command-line.customtags

Finally, there is one framework out there (that I know of, I'm sure there are tons) that uses annotations to do all sorts of restful goodness (perhaps saving yourself some work): https://github.com/recess/recess

Hope that helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜