To follow up on Rob Allen’s article about choosing a PHP framework for APIs, here is an edited discussion between Rob and a developer at a Seiden Group client regarding their new API.
In this discussion, Rob addresses common developer concerns about frameworks for APIs.
Developer: Our recent discussion about using Slim for our APIs was very interesting, but I have a few questions. To start, I should tell you that I always prefer lightweight tools. As I see it, the fewer extra third-party tools in my project, the better.
Rob Allen: There is always a trade-off. By writing your own version of common operations that are well-served by third-party libraries, you are spending your company’s opportunity cost of creating new unique business value. Sometimes there are good reasons to do so, but I would caution against blanket negativity to 3rd party libraries for parts of the codebase which have no specific business advantage.
There are costs to using a 3rd party library and there are costs to writing your own version. In most cases, the costs of writing and maintaining your own exceed the integration costs of a 3rd party library due to the opportunity lost.
Developer: When it comes to using Slim for our API server, I want to understand its benefits/advantages to justify having it as part of our codebase for the API server moving forward. I looked at it a while back, and although I appreciate that it is slimmer than other frameworks that I have seen, I feel it is something that I would most likely use if I were building a website or newer fully-functional application, rather than an API.
Rob: At its core, Slim, like other PHP frameworks, provides a router to decouple the URL from the code that executes. In an API, this allows for the URL to map to the design of the collections and resources in the API domain while allowing for the handler classes to be placed and named in the business domain as required.
For example, I can have POST /users map to the \App\Handlers\CreateUser handler class, which is completely separate from GET /users/groups which may map to the \App\Handlers\ListUserGroups handler. This mapper is a common requirement. Most PHP applications do it in some way or another with custom code that is not a business “unique selling proposition” for the company.
Developer: As far as the routing, I don’t see us making anything complex. For example, I figured we would have the routing follow the pattern /Controller/Method as some other projects do, which really only consists of a few lines of code.
Rob: For an API, a URL of the form /Controller/Method is very uncommon. API paths usually represent collections and resources.
- /users is the collection of users
- /users/rob_allen is the single user resource “rob_allen”
- /users/rob_allen/comments is the collection of comments that “rob_allen” has made
- /users/rob_allen/comments/cbccc942-a229-4131-b79f-2272fca52a26 is a specific comment
You don’t tend to see these mapped directly to a method class in a controller action without writing some routing code. By the time you get to the tenth collection, you end up refactoring to a generic solution that looks similar to a router in a web framework.
It always starts as a few lines of code and then grows. The question is, who should write and maintain them?
Developer: You also said a framework would help keep track of the call types such as POST, GET, PUT and DELETE. Granted, I will admit that most APIs I have done in the past probably didn’t follow the REST standard strictly. I just took everything as a POST and had the variables that came across in the post determine what was to be done with it. It would seem to me, however, that following the standard would really just be as simple as checking REQUEST_METHOD in the server variable in PHP to determine what to do.
Rob: Of course. Most coding is “simple” (though edge cases quickly make the simple complex!) There’s literally nothing in Slim or any other framework that you can’t do yourself. It’s where you do it, how you do it, how you document it and how you maintain it that are important.
Longer term, other developers join the company and have to use and maintain code that no one else other than you knows, and they have to depend on whatever documentation there is, especially if the original author has left the company.
The premise of using frameworks and 3rd party libraries is that the documentation and understanding of how to use them are more general than the specifics of one company. By using these libraries, we can redirect developer time to working on company-specific code, which is where the value and profit is.
Developer: It would seem that even using Slim we would need to determine what type of response to send, based upon what happens in our code. I imagine we would still need to set the response status codes in our application code, even if it is using some Slim function.
Rob: Yes. However you write the routing, you still need to send a response. In Slim, you return a PSR-7 standard response along the lines of:
return $response->withStatus(201)->withJson([‘user’ => $formattedUser]);
The response to a request in an API is usually JSON—but could be XML—and represents your view layer. In the same way that the returned HTML in a website is also your view, you need to create your API responses.
Developer: It seemed to me when I looked at Slim a while back that the current version of Slim was a lot different than the version that was used in an application we recently completed. Do you see Slim having major changes in the future in how it is used that would necessitate the need to rework our API code in order to keep up to date with the latest versions of Slim?
Rob: It shouldn’t have been. Slim 4 has been around for a couple of years and there are no plans to develop or release a version 5 at the moment.
As a good practice, though, you should decouple your business and view logic from the framework using separate classes that are injected into your framework’s handlers (controller actions) using dependency injection. This will minimize any issues.
Developer: If you could give me any further understanding I would appreciate it.
Rob: At the end of the day, the way an application is written is the decision of the team writing it. You can absolutely write a really good API using pure PHP and no third-party libraries.
My general thesis is that writing your own routing framework costs your employer more than the supposed simplicity in terms of developer time and expense, along with the cost of lost opportunity for those developers to work on application-specific features and the additional training costs for newly employed developers. Of course, you can disagree, and you may well be right for your particular situation.