Software Engineering in WordPress, PHP, and Backend Development

Tag: PHP (Page 1 of 12)

Strategies for Locally Developing Google Cloud Functions

For the last few months, I’ve been doing a lot of work with Google Cloud Functions (along with a set of their other tools such as Cloud Storage, PubSub, and Cloud Jobs, etc.).

The ability to build systems on top of Google’s Cloud Platform (or GCP) is great. Though the service has a small learning curve in terms of getting familiar with how to use it, the UI looks exactly like what you’d expect from a team of developers responsible for creating such a product.

An Aside on UIs

Remember how UIs used to look in the late 90s and early 00s? The joke was something like “How this application would look when designed by a programmer.”

UX Planet has a comic that captures this:

If developers were responsible for UIs.

I can’t help but think of this whenever I am working in the Google Cloud Platform: Extremely powerful utilities with a UI that was clearly designed by the same types of people who would use it.

All that aside, the documentation is pretty good – using Gemini to work with it is better – and they offer a CLI which makes dealing with the various systems much easier.

With all of that commentary aside, there are a few things I’ve found to be useful in each project in which I’m involved when they utilize features of GCP.

Specifically, if you’re working with Google’s Cloud Platform and are using PHP (I favor PHP 8.2 but to each their own, I guess), here are some things that I use in each project to make sure I can focus on solving the problem at hand without navigating too much overhead in setting up a project.


Locally Developing Google Cloud Functions

Prerequisites

  • The gcloud CLI. This is the command-line tool provided by Google for interacting with Google Cloud Platform. The difference in this and the rest of the packages is that this is a utility to connect your system to Google’s infrastructure. The rest of the packages I’m listing on PHP libraries.
  • vlucas/hpdotenv. I use this package to maintain a local copy of environmental variables in a .env file. This is used to work as a local substitute for anything I store in Google Secrets Manager.
  • google/cloud-functions-framework. This is the Google-maintained library for interacting with Cloud Functions. It’s what gives us the ability to work with Google Cloud-based function locally while also deploying code to our Google Cloud project.
  • google/cloud-storage. Not every project will serialize data to Google Cloud Storage, but this package is what allows us to read and write data to Google Cloud Storage buckets. It allows us to write to buckets from our local machines just as if it were a cloud function.
  • google/cloud-pubsub. This is the library I use to publish and subscribe to messages when writing to Google’s messaging system. It’s ideal for queuing up messages and then processing them asynchronously.

Organization

Though we’re free to organize code however we like, I’ve developed enough GCP-based solutions that I have a specific way that I like to organize my project directories so there’s parity between what my team and I will see whenever we login to GCP.

It’s simple: The top level directory is named the same as the Google Cloud Project. Each subdirectory represents a single Google Cloud Function.

So if I have a cloud project called acme-cloud-functions and then there are three functions contained in the project, then the structure make look something like this:

tm-cloud-functions/
├── process-user-info/
├── verify-certificate-expiration/
└── export-site-data/

This makes it easy to know what project in which I’m working and it makes it easy to work directly on a single Cloud Function by navigating to that subdirectory.

Further, those subdirectories are self-contained such that they maintain their own composer.json configuration, vendor directories, .env files for local environmental variables, and other function-specific dependencies, files, and code.

So the final structure of the directory looks something like this:

tm-cloud-functions/
├── process-user-info/
│   ├── src/
│   ├── vendor/
│   ├── index.php
│   ├── composer.json
│   ├── composer.lock
│   ├── .env
│   └── ...
├── verify-certificate-expiration/
│   ├── src/
│   ├── vendor/
│   ├── index.php
│   ├── composer.json
│   ├── composer.lock
│   ├── .env
│   └── ...
└── export-site-data/
    ├── src/
    ├── vendor/
    ├── index.php
    ├── composer.json
    ├── composer.lock
    ├── .env
    └── ...

Testing

Assuming the system has been authenticated with Google via the CLI application, testing the function is easy.

First, make sure you’re authenticated with the same Google account that has access to GCP:

$ gcloud auth login

The set the project ID equal to what’s in the GCP project:

$ gcloud config set project [PROJECT-ID]

Once done, verify the following is part the composer.json file:

"scripts": {
  "functions": "FUNCTION_TARGET=[main-function] php vendor/google/cloud-functions-framework/router.php",
  "deploy": [
    "..."
  ]
},

Specifically, for the scripts section of the composer.json file, add the functions command that will invoke the Google Cloud Functions library. This will then, in turn, allow you to run your local code as if you were writing it in the Google Cloud UI. And if there are errors, notices, warnings, etc., they’ll appear in the console.

To run your function locally, run the following command:

$ composer functions

Further, if you’ve got Xdebug installed, you can even step through your code. (And if you’re using Herd and Visual Studio Code, I’ve a guide for that.)

Deployment

Next, in composer.json, add the following line to your the deploy section as referenced above:

"deploy": [
  "gcloud functions deploy [function-name] --project=[project-id] --region=us-central1 --runtime=php82 --trigger-http --source=. --entry-point=[main-function]"
]

Make sure the following values are set:

  • function-name is the name of the Google Cloud Function set up in the GCP UI.
  • project-id is the same ID referenced earlier in the article.
  • main-function is whatever the entry point is for your Google Cloud Function. Oftentimes, Google’s boilerplate generates helloHttp or something similar. I prefer to use main.

Then, when you’ve tested your function and are ready to deploy it to GCP, you can run the following command:

$ composer deploy

This will take your code and all necessary assets, bundle it, and send it to GCP. This function can then be accessed based on however you’ve configured it (for example, using authenticated HTTP access).

Note: Much like .gitignore, if you’re looking to deploy code to Google Cloud Functions and want to prevent deploying certain files, you can use a
.gcloudignore
file.

Conclusion

Ultimately, there’s still provisioning that’s required on the web to set up certain aspects of a project. But once the general infrastructure is in place, it’s easy to start running everything locally from testing to deployment.

And, as demonstrated, it’s not limited to functions but also to working with Google Cloud Storage, PubSub, Secrets Manager, and other features.


Finally, props to Christoff and Ivelina for also providing some guidance along setting up some of this.

Use Static Variables in Plugin Bootstrap Files

As nice as event-driven programming can be within the context of WordPress’ hook system, one of the challenges is preventing code from executing every single time the hook is called.

For example, say you’re writing a function that fires during the init action but something happens in WordPress core that triggers the init action to fire again consequently causing your code to fire once again even though it’s unneeded.

Multiply this across however many callbacks spread across however many files and general functionality registered with the hook and you may end up affecting performance and/or executing code that has no need to be run.


Static Variables in Plugin Bootstrap Files

How an LLM thinks this post would look as an image.

One way this can happen is in a plugin’s bootstrap. Case in point: Say your plugin is registered with the init action and then it sets up a registry which in turn instantiates a set of subscribers that register services. Repeating this every single time init is fired is unnecessary.

Here’s a way to manage this:

add_action( 'init', 'tm_acme_function', 100);
function tm_acme_function() {
  static $initialized = false;
  if ( $initialized ) {
    return;
  }

  $initialized = true;

  // ... set up the rest of the function.
}

If you know how static variables work, you’re may already be doing this, you’re able to follow the above code, or both. And if that’s the case, there’s nothing else to see here.

But if not, static variables can be useful in this scenario because static variables maintain state between calls whereas regular variables are reinitialized every time the function fires. This means a static variable retains its value across multiple calls to the function.

Static Variables and Plugins

So having an static $initialized flag works like this:

  • $initialized starts as false.
  • When the function runs for the first time, the $initialized variable is set to true.
  • On subsequent calls, the condition if ( $initialized ) prevents the rest of the function from executing, effectively short-circuiting it.

And because of that, this:

  • prevents redundant execution,
  • optimizes performance by avoiding running unnecessary code (especially as it relates to registering duplicate functionality, running multiple queries, or trashing data unintentionally).

If your plugin’s bootstrap registers a callback with a WordPress hook, considering using static variables to prevent code from being called unnecessarily more than once.

How To Identify Anonymous Functions in WordPress

Heads Up! Originally, I wanted to include both how to identify anonymous functions in WordPress and how to unhook them; however, the more I began writing about the topic, the longer the article became.

So I’ve split the content into two articles: This one outlines how to identify anonymous functions registered with hooks. A future article will detail how to de-register said functions.


Previously, I explain how to identify and register anonymous functions in WordPress. As I wrote in the introduction:

As I started writing, it became obvious it’s helpful to understand what PHP does behind-the-scenes when anonymous functions are registered.

So during the first article, I spend time explaining both how anonymous functions are registered – which is clear enough – and how anonymous functions are managed internally by PHP.

If you haven’t read the article, I urge you to do so. But if you’re opting out, the short of it is this:

  1. You register an anonymous function with an associated WordPress hook,
  2. PHP generates an ID via hashing for the anonymous function so that it can be managed internally.

It sound easy enough, but problems arise if you want to programmatically identify those anonymous functions. PHP keeps track of them and the functions fire as they are intended but what happens if you, as a developer, want to access those functions to deregister them?


Identify Anonymous Functions

Before looking how, or if, it’s even possible to deregister anonymous functions, it’s important to know how to identify anonymous functions programmatically. That is, if we know we’re working in an environment where anonymous functions have been registered, how do we actually find them?

This programmer is completely at a loss for where to find an anonymous function.

Again, since these functions are registered with WordPress hooks and since these functions have an ID internally generated by PHP, there’s code we can write to help us understand where these functions are registered.

In the following bit, I’ll show exactly how to do this. This won’t necessarily explain what the code is going nor will it explain who registered the code, but it’ll give us some insight as to what anonymous functions are registered with which hooks.

And that’s a good starting place.

Finding Anonymous Functions

Before using any other specific tools, I’m going to use the following:

It’s not pretty, this isn’t the usual set of tools with which I’d recommend using, but it’s a starting point that’s going to demonstrate the point. In other words, this is a quick and dirty approach to get started.

Further, we’ll be writing anonymous functions in the theme’s functions.php to make it easier to have parity with the content of the article.

With all of that in place, I’ll open functions.php and then add the following code:

add_action('wp_head', 'listRegisteredFunctions', PHP_INT_MAX);
/**
 * Lists all the registered functions.
 *
 * @return void
 */
function listRegisteredFunctions() {
     global $wp_filter;

     echo <<<HTML
     <div style="background:white; font-size:14px;">
         <pre>
    HTML;
        print_r($wp_filter);
    echo <<<HTML
         </pre>
     </div>
     HTML;
 }

This uses the global $wp_filter object which holds information on all of the referenced actions and filters with WordPress. Note also that I’m setting this up to fire in the wp_head hook and that I’m using PHP_INT_MAX to make sure it has the highest priority (so it fires as late as possible).

Note: I do not recommend nor even suggest using PHP_INT_MAX in a production environment because it makes it incredibly difficult to add anything after that registered hook. This is just for demonstration purposes.

If you run this and then refresh the homepage of your installation, you’re going to see a lot of information. Some of it will make sense, some of it may not. Regardless, it’s going to be a lot of data. And as interesting as it is, there’s not much we can do with it.

If there’s not much to do about it, might as well laugh about it.

To help simplify what it renders, let’s look at something that’s registered with just one of the hooks. Specifically, let’s look and see what’s registered with the wp_enqueue_scripts hook. This hook is one that most anyone who has worked with theme or plugin development has used and something that’s going to have a number of associated callbacks within the context of a theme.

Note, I’m going to use a similar function as used above. I will, however, be changing the actual code in the function. Additionally, note that I have some guard clauses defined for early return so that if nothing is registered with the hook or if there are no callbacks, the function won’t run.

The code looks like this:

add_action('wp_head', 'listRegisteredFunctions', PHP_INT_MAX);
/**
 * Lists all the registered functions.
 *
 * @return void
 */
function listRegisteredFunctions() {
     global $wp_filter;

    if (!isset($wp_filter['wp_enqueue_scripts'])) {
        return;
    }

    // Get all functions/callbacks hooked to wp_enqueue_scripts
    $callbacks = $wp_filter['wp_enqueue_scripts']->callbacks;
    if (empty($callbacks)) {
        return;
    }

    // ...
}

It’s not going to render anything yet, though, because I don’t have the code for actually rendering the callbacks and functions associated with the hook. To do that, we can iterate through the callbacks and get each function and its associated priority.

To render that, we need to add:

echo '<pre>';
foreach ($callbacks as $priority => $functions) {
    foreach ($functions as $function) {
        print_r([$function, $function['function']]);
        echo '<br />';
    }
}
echo '</pre>';

The two important things to take away from the above code are:

  1. I’m adding the function and the $function['function'] to an array that’s dumped by print_r.
  2. $function['function'] contains a reference to the callback function.

In the outer foreach loop, note that $functions is the associative array representing the callbacks hooked to the wp_enqueue_scripts. In the inner loop, $function has information about the callback and $function['function'] is the actual callback itself.

In the environment I’m using to test this code, I’m running the twentytwenty theme and I’ve added the above code to functions.php. If you’re following along with the same – even if it’s a different theme – you’ll likely see something like this written out to the screen:

Array
(
    [0] => Array
        (
            [function] => twentytwenty_register_scripts
            [accepted_args] => 1
        )

    [1] => twentytwenty_register_scripts
)

I’ve opted to use this as an example because it’s prefixed with twentytwenty_ meaning it’s likely going to be found within the theme. And when I search for this function in the theme within my IDE, I found the following:

/**
 * Register and Enqueue Scripts.
 *
 * @since Twenty Twenty 1.0
 */
function twentytwenty_register_scripts() {
    // Code remove to keep the code succinct.
}

add_action( 'wp_enqueue_scripts', 'twentytwenty_register_scripts' );

The important thing to note here is that we see the function twentytwenty_register_scripts is, in fact, registered with the wp_enqueue_scripts hook.

The purpose of looking at this is to see that we’re successfully able to find code that’s registered with our hook of choice. The next challenge, though, is finding anonymous functions that are registered with the same hook.

Sometimes, printing out the code and searching for anonymous functions helps. Supposedly.

You can argue that it’d be more helpful to go ahead and find all anonymous functions registered with this hook but let’s first create out own so we can get an idea as to how this looks.

When doing this, you’ll see how complex, though not impossible, managing anonymous functions can be.

Creating Our Own Anonymous Function

First, comment out the code that’s listing all of the functions registered with the wp_enqueue_scripts hook.

This dude thought registering a function with a hook literally meant he needed a hook.

Next, let’s add our own anonymous functions to functions.php. This will render a message at the top of the page and it will allow us to use previously written code to track track this anonymous function.

add_action('wp_enqueue_scripts', function () {
    echo <<<HTML
        <div style="border:1px outset gray; padding: 1em;background:#ccc;position:fixed;top:0;left:0;z-index:99; width: 100%;">
            This is a a sample anonymous function.
    </div>
    HTML;
}, 0, 10);

When you refresh the page you’re on, you should see something like this:

The next step will be to run the previously written code and attempt to locate this function.

Now let’s reintroduce the code responsible for printing all of the functions registered with the hook. Assuming you’ve done everything correct, you’ll notice a new piece of data rendered on the page.

Specifically, it’ll read like this:

Array
(
    [0] => Array
        (
            [function] => Closure Object
                (
                )

            [accepted_args] => 10
        )

    [1] => Closure Object
        (
        )

)

Assuming there are no other anonymous functions in your code, then this is the function we just wrote and the one we’re looking to manage.

When dressed like this in a place like that, you’re ready to manage all of the code.

So this raises the following two questions:

  1. How can we relate an anonymous function to a specific hook?
  2. How can we de-register this function?

Since we know that PHP generates an internal ID for closures and since we have an anonymous function currently hooked to the wp_enqueue_scripts hook, let’s see what we can do.

Relating Anonymous Functions to Specific Hooks

First, let’s update the code in functions.php so that it dumps all of the information for the closure. I’ll show the code first then explain what it’s doing:

add_action('wp_enqueue_scripts', function () {
    $backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
    echo '<pre>';
    var_dump($backtrace[1]['object']);
    echo '</pre>';
    // The original code is here...
});

Note this part is going to require a bit of functionality offered by PHP. Some of you who have worked with PHP for years may be familiar with this; some of you may not. And if not, that’s okay! I’ll explain it then share a bit more about it.

In the function, I’m grabbing information from one of the built-in PHP functions called debug_backtrace and then I’m using the DEBUG_BACKTRACE_PROVIDE_OBJECT constant to help.

This is a breakdown of each argument and the function to which they are passed:

  • debug_backtrace() is a function in PHP that returns a backtrace, which is an array of associative arrays containing function call information. It provides a snapshot of the call stack at the point where it is called, showing the hierarchy of function calls leading up to that point.
  • DEBUG_BACKTRACE_PROVIDE_OBJECT is a constant flag that can be used as an option when calling debug_backtrace(). When this flag is set, each frame in the backtrace will contain an entry named ‘object’ representing the current object instance.
  • The 2 is an optional parameter specifying the number of stack frames to return in the backtrace. In this case, it limits the backtrace to two frames.
  • And, for what it’s worth, a “frame” refers to a specific level or entry in the call stack (which is, essentially, the order in which functions are called).

This is what a call to this function actually does:

  • The first frame is the frame where debug_backtrace() is called (that is, the anonymous function itself).
  • The second frame is the frame where the function that called debug_backtrace() resides.
  • By limiting the frames to two, you get information about the current function (anonymous function in this case) and its caller.

As I mentioned at the start of this section, using functionality like this is something that comes with having worked with PHP for several years. I don’t remember exactly when I learned it myself. Regardless, that’s an advantage of articles like this, I guess (read: I hope) – it exposes you to new things of which you may not have otherwise been aware.

And yes, de-registering hooks in WordPress is challenging but it’s through these type of facilities that we should be able to do so. When you view this code in your browser, you should see something like the following located in the data you’ve printed to your browser:

["00000000000002e50000000000000000"]=>
array(2) {
  ["function"]=>
  object(Closure)#741 (0) {
  }
  ["accepted_args"]=>
  int(1)
}

Recall from the previous article that PHP does two things when registering callbacks:

  1. Generates an ID for the closure. To generate a unique identifier for this closure, WordPress uses the spl_object_hash() function.
  2. Associates the ID with the callback. The generated closure ID is then associated with the callback function, allowing WordPress to track and manage callbacks even when they are anonymous functions.

And since this is an anonymous function, the ID we see in the print out above is the ID PHP generated when registering the function.

Before We Deregister The Function…

As I stated throughout this article: I wanted to include all of the information in the previous article and this article to explain exactly what PHP is doing, how to locate registered closures, and how to deregister them, but the amount of time it takes to explain how to do all of the above takes longer than I anticipated.

It took so long for this guy to explain the concepts, his audience fell asleep. Maybe his handwriting should be better.

As such, I’m going to pause here. There’s plenty of material to review in terms of the PHP internals as well as work that can be done to inspect your own anonymous functions.

In the next article, I’ll walk through a process – regardless of how manual it is – for how to deregister the functions.

Until then, incorporate some of the code here and also see what other anonymous functions have been registered throughout your codebase.

Identifying and Registering Anonymous Functions in WordPress

Originally, this article started as an explanation for how to remove anonymous functions registered with WordPress. As I started writing, it became obvious it’s helpful to understand what PHP does behind-the-scenes when anonymous functions are registered.

This dude clearly doesn’t understand anonymous functions. The eyes give it away.

Furthermore, this helps give a deeper understanding as to why registered anonymous functions can be problematic and how we can deal with them on a technical level.

Finally, it’s worth noting that I don’t take a hard stance on if anonymous functions should never be used or not. There’s a time and a place where it makes sense, and there’s a time and a place where it doesn’t need to be done. That’s a topic to cover in the future, though.


I’ve mentioned this before, but I’m not in the business of sharing the author of any given tweet [anymore] for the sake of how X/Twitter mobs can behave. Besides, it’s the content of the tweet that warrants a discussion, not the person who said it.

Some time ago, I saw this come across my feed:

I do wish developers would stop using WordPress hooks with (what I think are called) anonymous functions […].

They are very hard if not impossible to unhook.

As mentioned, the how to deregister anonymous functions and the “whether or not this is a good idea” are topics for another post. For now, I want to share what happens whenever an anonymous function is registered with a hook in WordPress.

Named Functions in WordPress and PHP

Brainstorming names for named functions. Naming things is hard.

First, an example:

add_action('admin_init', 'tmAddBackgroundColor');
function tmAddBackgroundColor()
{
    echo '<style>
            body {
                background-color: #f3f3f3;
            }
          </style>';
}

In the code above, we’re using a named function – as opposed to an anonymous function – to do the following:

  • add_action('admin_init', 'tmAddBackgroundColor') hooks the tmAddBackgroundColor function to the admin_init action. It tells WordPress to execute the specified function when the admin area is initialized.
  • The actual function adds a custom CSS style to the admin area.

If I was a third-party developer who wanted to remove this functionality, then I’d locate the function and invoke the following call somewhere in my code:

remove_action('admin_init', 'tmAddBackgroundColor');

This is an obvious benefit to named functions. Even if the function is located in a different namespace, it’s possible to remove the action by prefixing the function name with the name of the namespace.

What happens with anonymous functions, though?

Anonymous Functions in WordPress and PHP

You don’t have to name an anonymous function. You might as well just stare at a wall.

If you’re familiar with anonymous functions, then the following code should be clear. If not, though, take a look and I’ll explain what’s happening after the block:

add_action('admin_init', function () {
    echo '<style>
            body {
                background-color: #f3f3f3;
            }
          </style>';
});

Anonymous functions are generally useful when you have a small, one-time callback that doesn’t need to be referenced elsewhere in your code.

Obviously, the functionality is the same, but it raises the question: How do we call remove_action on this function? That’s something we’re working towards, but first, here’s what happens in PHP whenever you’re working with anonymous functions.

PHP Closures, Closure IDs, and Registration in WordPress

An ID registered for a conference.

Before reading any further, note that a closure in PHP is a way to create an anonymous function.

Just like what’s demonstrated above, it allows us to write a piece of code that can be registered with a hook or, more generally, passed around as a variable. The latter part of this will make sense after we look at what PHP does when an anonymous function is created.

PHP does two things after you register an anonymous function with a WordPress hook:

  1. Generates an ID for the closure. To generate a unique identifier for this closure, WordPress uses the spl_object_hash() function.
  2. Associates the ID with the callback. The generated closure ID is then associated with the callback function, allowing WordPress to track and manage callbacks even when they are anonymous functions.

Given this, another way to write and associate an anonymous function with WordPress would be like this:

$adminInitCallback = function () {
    echo '<style>
            body {
                background-color: #f3f3f3;
            }
          </style>';
};

add_action('admin_init', $adminInitCallback);

And we can get the ID of the closure as generated by PHP by passing the variable to the spl_object_hash function. For example:

$closureId = spl_object_hash($adminInitCallback);

And that will return the ID that’s generated by PHP and associated with the specific hook in WordPress.

But Still, Deregistering Anonymous Functions?

Though this doesn’t help explain how to deregister anonymous functions, it does help explain how things work within PHP.

This will make it easier to explain ideas around anonymous functions ands hooks in a future post.

Why We Don’t Always Need Do Perform an Early Return

There are a lot of opinions on how return statements should work.

  • Some say that there should be a single point of return in a function,
  • Some day we should return as early as possible,
  • Some day multiple return statements are fine,
  • And some say that, when applicable, return as early as possible.

I’m sure I’m missing some, but all of these are ones I’m sure the majority of you have seen. And though I don’t hold either of these to be law, I think there’s a time and a place for each.


I’m a fan of the early return statement. In my mind, the sooner we can determine we don’t need to do the work of a function, the better we just leave.

For example, say we know if we’re not on a certain page, we can go ahead and leave the function:

In this case, it makes sense because:

  1. You only want to perform work on the plugins.php page,
  2. The amount of work to be done in the function is larger than what should ever fit within a conditional.

But there’s an alternative when the amount of work is less than what’s above.

Continue reading
« Older posts

© 2025 Tom McFarlin

Theme by Anders NorenUp ↑