0% found this document useful (0 votes)
14 views

Flexible API Design - Create Hooks For Your PHP API Pipeline - SitePoint

Uploaded by

Luis Cortes
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Flexible API Design - Create Hooks For Your PHP API Pipeline - SitePoint

Uploaded by

Luis Cortes
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

PHP / APIs / Flexible API Design: Create Hooks for Your PHP API Pipeline

Tim Hurd

Flexible API Design: Create Hooks


September 8, 2021

for Your PHP API Pipeline


APIs PHP Programming Web

Share this article


Table of Contents
What Are Hooks/Actions?
Why Use Hooks in an API?
Building the Basic Mechanisms
Where Can We Place These Hooks?
Best Practices
Conclusion
Frequently Asked Questions (FAQs) on Flexible API Design and PHP Hooks

Designing application programming interfaces (APIs) can be a challenging endeavor.


Good APIs have simple interfaces that are straightforward and easy to use. Behind
this simple interface can be many complex system interactions, and those
interactions can really muddy the waters of an otherwise clearly defined endpoint
task. Over time, developers may be asked to “tack on” additional business logic for
existing endpoints. Then before you know it, a single API call is making interactions
with over a dozen systems as part of its main flow.

ADVERTISEMENT

Wouldn’t it be nice if we could develop a pipeline that’s straightforward but with the
capability to add additional tasks later without obscuring the main flow? This article will
show you how you can adapt an idea from WordPress, and programming in general, to give
your APIs the ability to do more powerful interactions.

What Are Hooks/Actions?


A hook (aka actions/filters) is the name given to events and their related callbacks by the
WordPress community. If you have any experience in programming, you might be familiar
with callbacks and the publisher–subscriber pattern. During processing, a system may
trigger an event which calls zero to many functions subscribed to that event. For instance, in
response to loading a page, WordPress makes calls to functions for loading the header,
loading a title, listing posts or looking for the right template. These tasks are run without
cluttering up the main process of generating a page.
The idea behind hooks is nothing new and wasn’t invented by WordPress. However,
WordPress did a great job of implementing them during their server-side page processing
lifecycle. This use of hooks, in my opinion, is probably the single greatest feature the
platform has. With these hooks, users can write their own functionality — be it plugins or
themes — that tie into WordPress and run whatever code you want right when it’s needed.
Do you need to alter a header sent to the user? No problem: hook into the wp_headers
event and you can alter the headers as you see fit.

Why Use Hooks in an API?


Hooks are good for many things, including triggering some side tasks, calling out to another
system through a PHP cURL command, building an object and putting it into a task queue to
be picked up by another system later, sending an email, and more. This can all be done
without needing to cloud the main flow of a given endpoint (and possibly forcing a new API
version in the process).
If the endpoint is for creating a user, we can focus on creating that user record in the
database and along the way just call out to whoever is listening during that process. Maybe
after creating the user record, we send out an event that says “anyone listening to this, I just
created a user and here’s their info”. Maybe some callback functions have subscribed to the
event and are listening or maybe none are. The event doesn’t really care.
With this system, we can have our APIs call out to code that may be written at some later
time. We can do this without needing to touch the API endpoint code itself. To demonstrate
how this might work, let’s change gears and show the basic mechanism of how we can get
this started in a PHP API. Do keep in mind that, while we’re using PHP here, we can actually
implement similar logic in web applications using other languages.

Building the Basic Mechanisms


To get started, we’ll need to be able to add a hook/action (which I’ll refer to as “hook” from
now on). We’ll also need the ability to remove a hook and lastly trigger a hook. Once we
define these mechanisms, we just need to make sure they’re included into the API and then
locate places in our API where we might want to call these hooks. Below is one way we
might want to set this up.
Here’s hooks.php :

// Global array which will hold all of our hooks


// We will reference this array in each function to add/remove/call our hooks
// The code below should also be seen by any callbacks we write for the system
$hooks = [];

// Below are global functions that can be seen from our API code
// The add_hook method will allow us to attach a function (callback) to a give
function add_hook($event_name, $callback) {
global $hooks;

if ($callback !== null) {


if ($callback) {
// We can set up multiple callbacks under a single event name
$hooks[$event_name][] = $callback;
}
}
}

// Super easy to implement, we remove the given hook by its name


function remove_hook($event_name) {
global $hooks;

unset($hooks[$event_name]);
}

// When we want to trigger our callbacks, we can call this function


// with its name and any parameters we want to pass.
function do_hook($event_name, ...$params) {
global $hooks;

if (isset($hooks[$event_name])) {
// Loop through all the callbacks on this event name and call them (if d
// As we call each callback, we given it our parameters.
foreach ($hooks[$event_name] as $function) {
if (function_exists($function)) {
call_user_func($function, ...$params);
}
}
}
}

Now that we have our hooks.php file created, we simply need to include it into our API so
that these functions can be seen. Once this is done, it’s just a matter of inserting the hooks
into our API using do_hook .
As a simple example, let’s assume we have an API for registering a new user with our
system. We may have a REST API endpoint called /addUser . In the name of simplicity, let’s
also assume that the goal here is to simply insert a new user’s name and age into our
database’s users table. Pretty straight forward, right?

// POST endpoint for adding a user (part of a larger API class)


public function addUser($name, $age) {
if ($this->request->method === 'post') {
try {
$this->db->insert('users', ['name' => $name, 'age' => $age]);
return new Response(200, 'User created successfully!');
} catch (Exception $e) {
// Oops, something went wrong.
// Do some logging or whatever.
}
}

// If not a POST request, return http status 400


return new Response(400, 'Bad request');
}

The code above is an overly simplistic and generalized view of how we might add a new
user. The idea is that, if someone were to call our API’s /addUser endpoint, they would
eventually arrive at this function where the name and age of the user is pulled out of the
posted data. We first check to make sure they’re posting (as proper REST rules dictate) and
then try to insert the user into the users table.
Next, if the user has been inserted successfully, we want to call a hook to let any code
listening that a user was created (this is similar to raising an event in other languages).
ADVERTISEMENT
What to do when requirements change
A few months later, we have our marketing department insisting that, when a new user is
created, an email should be sent with the user’s details. We might be inclined to write a
helper function into the API, then call it from this endpoint code. Great … if that’s all that was
requested. But what if the support team later comes to you and wants you to also add the
user to their Zendesk system. So you write another function and tack that call into this
endpoint also.
Next thing you know, this endpoint is not only adding a user to our website database, but
making calls to functions for sending emails, adding users to Zendesk, Jira and the Microsoft
cloud and then dealing with their success/failure results. All this additional stuff is really
taking away from the clear point of adding the user to our database. We’d like to call one
event and have other code just listen for when a user is created and do their own things —
without us needing to modify this endpoint whatsoever. Perhaps no other services care
about adding a new user, so no one is called upon to do anything. The endpoint doesn’t have
to care. Pretty awesome, right?
Let’s continue our example by giving our hook a name. This is the name that all callback
code will need to use to listen. Again, other languages refer to this setup as “events”, so be
sure to look it up in your given language to learn more.
We’ll call our hook added_user . Simple and straight to the point, don’t you think? Once we
have a name, we can decide where we want to call this hook. I think right after a successful
insert would be a good idea:
public function addUser($name, $age) {
if ($this->request->method === 'post') {
try {
$this->db->insert('users', ['name' => $name, 'age' => $age]);
// Call our new hook and give it the name and age of the user. Anyone li
do_hook('added_user', $name, $age);
return new Response(200, 'User created successfully!');
} catch (Exception $e) {
// Oops, something went wrong.
// Do some logging or whatever.
}
}

return new Response(400, 'Bad request');


}

 

Now we can have dozens of callback functions listening to the added_user hook or none at
all. Maybe we have one callback that’s responsible for inserting the user into Zendesk and
another that will take the name and age and generate an email to marketing. This
“subscriber” code can live somewhere else in the codebase, as long as it can see the
hooks.php code inside the API project. I typically put my callback function in a separate file
and include that file into the API as well. Below is one example of a callback that can now
take advantage of this new hook we created:
function sendContactToMarketing($name, $age) {
// Do email stuff
}

add_hook('added_user', 'sendContactToMarketing');

Where Can We Place These Hooks?


In the code above, we demonstrate using a hook in a single endpoint. This hook is only
triggered when the /addUser endpoint is called, and only after the insert succeeds. But this
isn’t the only place you can use these hooks. Perhaps you have some routing code in your
API class that runs through checking if an API key is valid or that you even received a certain
type of request.
You could put a hook in at a global level within the API so that every request triggers it. Then,
at some later time, someone could write a logger, attach it to the api_init hook you
created and suddenly start logging all requests made to the API — again, not touching the
main API class code. That same hook may also have an additional callback attached that
would check for API abuse and report it to your Information Technology department if it
starts seeing someone slamming your API with requests.
The image below is a diagram of how this all looks architecturally.

Since you can use this mechanism in multiple locations, you can even have hooks called at
the beginning, middle and at the end of an API endpoint. You could also have hooks at
various points of the entire API lifecycle of handling a request. It’s really up to your design on
where you insert these do_hook calls.
Best Practices
Let’s now cover some best practices for you and your developers to follow.

Tip 1: Keep your hooks lean and mean


ADVERTISEMENT

One thing to keep in mind is that these hooks still do call out to code that will execute in the
single thread. Unless you trigger something in your callback which kicks the task to some
background process or other service, the API will still be running this extra code (when the
hook is triggered). This means that we should do our best to keep any callback code lean
and mean. Long-running callback code is going to slow down the endpoints or the API as a
whole.

Tip 2: Make each callback isolated and simple to debug


However, with the way this structure is designed, adding and removing callback functions for
your hooks is easy to do and debugging is just as easy. Find which callback is the offender
(maybe have each callback log some data) and find out where it’s getting stuck. Then simply
don’t have it subscribe to the hook until the bug is fixed or work through the callback code,
again not touching anything within the endpoint/API code and not preventing your API code
from running in production.
Tip 3: Think about performance and don’t abuse a hook
It’s also important to be mindful of how many callbacks you attach to your hooks. A handful
of quick callbacks is fine, but 100 callbacks on a single hook with each taking one second to
execute can really be a drag on your API. We want fast API calls, and each callback can
easily drag on response times. Again, if you find a callback slow, throw the task out to a
background process or a queue system to be picked up by another service later. I often use
jobs in systems like Laravel to handle such tasks. Maybe add the user task to a Laravel job
queue and continue on with API processing.

Tip 4: Stay in touch with your dev community


Lastly, make sure you stay in touch with your developers who might be using these hooks.
It’s common that developers using your hooks, and writing callbacks, aren’t the same people
who created the hook in the API to begin with. As your API matures, you might start seeing
requests to add more hooks in different places and with finer granularity. They might ask for
before/after hooks that can be used to trigger actions before a user is inserted as well as
after. They may also ask for additional info to be passed to their callbacks (not only their
name and age but also the new ID of the inserted user, for example). Take these requests as
a good sign that your devs find the mechanism useful and see the potential of expanding
your API’s impact in related systems. It really feels good to have a system that’s so easy to
“hook” into and execute a small piece of code to have a large impact.
With this approach, the sky’s the limit on what you can have your API do. This all can be
achieved while keeping your endpoint’s main flow clear and free from noise when dealing
with other systems.

Conclusion
In this article, we discussed what hooks/actions are and how they might be used. We gave
some example PHP code that you can use in your PHP API to implement “hooking” and how
a callback might be used to tie into that hook. We also discussed adding hooks on a general
API level (more globally for all requests) as well as in endpoints. In addition to that, we also
talked a bit about some of the drawbacks of this system and that it’s a good idea to keep
your callbacks lean and mean. But in the event you do have a long-running callback, we
mentioned a few strategies for dealing with such processes to prevent them from impacting
your API pipeline.
If you implement this system, you too can gain some of the greatest functionality that the
WordPress community (and programmers in general) have enjoyed for years. You’ll also save
yourself a lot of time and headaches from having to modify your API code directly, and you’ll
be able to focus on small callback code instead. You can also add and remove callbacks that
may be entire integrations with other systems. All this functionality — and not once having to
republish your API pipeline code! That’s a pretty good deal, right? With this system, I’ve
managed to do some simple integrations in a day, and now you can do it too.
Thanks for reading!

Frequently Asked Questions (FAQs) on


Flexible API Design and PHP Hooks
What is the significance of hooks in PHP API pipeline?
Hooks in PHP API pipeline play a crucial role in enhancing the flexibility of an application.
They allow developers to insert custom code at specific points in the program execution
without altering the core code. This makes it easier to add, modify, or remove functionalities
without disrupting the entire system. Hooks are essentially events triggered by specific
actions, and they can be used to extend the application in a clean and organized manner.
How can I create hooks for my PHP API pipeline?
Creating hooks for your PHP API pipeline involves defining specific points in your code where
custom code can be executed. This is typically done using events and listeners. When a
particular event occurs, the corresponding listener is triggered, executing the custom code.
This allows you to modify the behavior of your application at runtime, providing a high
degree of flexibility and adaptability.
What are the best practices for designing a flexible API?
Designing a flexible API involves several best practices. Firstly, it’s important to keep the API
simple and intuitive, making it easy for developers to understand and use. Secondly, the API
should be designed to be extensible, allowing new features to be added without breaking
existing functionality. Thirdly, it’s crucial to provide clear and comprehensive documentation,
helping developers understand how to use the API effectively. Lastly, using standard HTTP
methods and status codes can make the API more predictable and easier to use.
How does PHP compare to other languages for API design?
PHP is a popular choice for API design due to its simplicity and flexibility. It supports a wide
range of data formats, including JSON and XML, making it easy to create APIs that can be
consumed by various clients. PHP also has a large and active community, providing a wealth
of resources and support for developers. However, like any language, it has its strengths and
weaknesses, and the choice of language should be based on the specific requirements of
the project.
What are some common challenges in API design and how
can they be addressed?
API design can present several challenges, including ensuring consistency, managing
versioning, and handling errors effectively. Consistency can be maintained by following
established conventions and standards. Versioning can be managed by including the version
number in the API URL or request header. Errors should be handled gracefully, providing
clear and helpful error messages to help developers diagnose and fix issues.
How can I ensure the security of my API?
Ensuring the security of your API involves several measures. This includes using secure
communication protocols such as HTTPS, implementing authentication and authorization
mechanisms, and validating and sanitizing input data to prevent injection attacks. Regular
security audits and updates can also help to identify and fix potential vulnerabilities.
How can I test my API to ensure it’s working correctly?
Testing your API involves making requests to the API endpoints and verifying the responses.
This can be done manually using tools like Postman, or automatically using testing
frameworks. It’s important to test all aspects of the API, including functionality, performance,
and security.
How can I handle errors in my API?
Handling errors in your API involves returning appropriate HTTP status codes and error
messages. This helps developers understand what went wrong and how to fix it. It’s also
important to log errors for debugging and analysis.
How can I improve the performance of my API?
Improving the performance of your API can involve several strategies, including optimizing
database queries, implementing caching, and using efficient data structures and algorithms.
Regular performance testing and monitoring can help to identify bottlenecks and areas for
improvement.
How can I keep my API up to date with changing
requirements?
Keeping your API up to date involves regularly reviewing and updating the API design based
on feedback from developers and changes in business requirements. It’s also important to
communicate any changes to the API users in a timely manner, and to provide support for
older versions of the API where necessary.

Tim Hurd View Author


Tim is a Canadian programming mentor, author, Senior Full Stack developer and founder of
The Coders Lexicon. For the past 23+ years he has been specializing in web integrations,
API design and system architecture for enterprises in multiple industries including
telecommunications, travel and photonics. He spends his time helping other developers with
their solutions and contributing over 14k posts covering not just the web, but desktop
development as well. He can be found wandering the web through @MartyrsCry.

api

Share this article


Read Next

100 Jamstack Tools, APIs & Content as UX: Building a Getting Started With The
Services to Power Your More Human Web Particle Photon
Sites Georgina Laidlaw Patrick Catanzariti
Lucero del Alba

CSS Architectures: New Building an Ad Manager in Hassle-Free Filesystem


Best Practices Symfony 2 Operations during Testing?
Denise Jacobs Kitty Giraudel Yes Please!
Reza Lavarian

15 React Interview Sinatra Up and Running: A


Questions with Solutions Book Review
Nilson Jacques Darren Jones
Get the freshest news and resources
for developers, designers and digital
creators in your inbox each week

Start Free Trial

Stuff we do Contact
Premium Contact us
Newsletters FAQ
Learning paths Publish your book with us
Library Write an article with us
Forums Advertise
About Connect
Our story RSS
Corporate memberships Facebook
Terms of use Instagram
Privacy policy Twitter (X)
This site is protected by reCAPTCHA and the Google Privacy
Policy and Terms of Service apply.

© 2000 – 2024 SitePoint Pty. Ltd.

Back to top

You might also like