Technical Tuesday: Another Look at WordPress register_activation_hook

(Reading time: 7 – 11 minutes)

Wait! Stop!

There’s much more here than source code. You can skip right over the register_activation_hook example code. Unless you’re desperately seeking solutions, then you want to read every word.

Still with me? Cool. Let’s get started.

Technical documentation is hard to read and harder to write. As a programmer, you aren’t rewarded for writing documentation, no matter what management says, so documentation tends to be lean, spare.

As a reader, you know you’re putting on the turswiry hat before you even crack open the manual.

When you finally break out the manual, you’re invariably faced with learning about how complicated it all is. Then,

Once you figure it out on your own, you can’t say the man pages don’t say that. – Jason Cox.

Wisdom from East Tennessee indeed.

It’s that “figure it out on your own” part that’s so hard. It takes a lot of practice, both to do the figuring, and knowing when you need to take the time to do the figuring.

Because it is time consuming.

Here’s my practice “figuring it out” for today.

(Non-programmers, skip past the code).

Example code from WordPress.org forum

WordPress is a large and rich application. It’s fairly well written; I’ve seen far worse code. And it’s fairly well-documented.

But there are still a lot of dusty corners. One of these is the register_activation_hook function. Most plugins need to use, but there’s not a lot of accurate discussion about exactly how to use it.

I was poking around for some example code, and ran across this snippet posted by Gleb Esman. Gleb seems pretty cool, he’s the author of the MemberWing plugin and service. But he didn’t get this one right, and I’m going to show you why. Let’s take a look:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
/*
Plugin Name: A Test
Description: A Test
*/
 
require_once (dirname(__FILE__) . '/my_other_file.php');
 
// This code *will not* work. Activation hook function must be defined in the main plugin file.
//register_activation_hook (dirname(__FILE__) . '/my_other_file.php', 'my_other_function');
 
//(Dave) But this code works just fine! 
register_activation_hook (dirname(__FILE__) . '/activation1.php', 'my_other_function');
register_deactivation_hook (dirname(__FILE__) . '/activation1.php', 'clean_em_up');
 
// This code will work.
//register_activation_hook (__FILE__, 'test_activated');
 
// This is correct way to declare/access globals.
global $some_var;    // globals must be declared explicitly. Without this you will not be able to access '$some_var' from within 'test_activated()' function.
$some_var = 'hey';
 
//===========================================================================
function test_activated ()
{
   global $some_var; // Now it will be 'hey'.
 
   // This function is defined in 'my_other_file.php'
   my_other_function ();
 
   // This will not work, so don't try. If you need logging write something in temporary log file in here via fopen/fwrite.
	// If you want to quickly test if your activation hook works - put exit() into it. At least you'll see error during activation.
   echo 'test_activated called!';
}
//===========================================================================
?>

First, please accept my apologies for the misaligned line numbers. This is a Thesis CSS issue, the table layout design between Thesis and the plugin doesn’t work very well. But it’s still workable. Let’s walk through it line-by-line:

  • Line 3: the plugin name. Critical. We’ll return to this later.
  • Line 7: I’ve listed this file below as well, we’ll look at it line by line next.
  • Line 10: Doesn’t work, true, but the explanation is wrong.

    Fact: WordPress will register any callback in scope.

    The problem here is that activation hook operates on the plugin name. The name of the file (line 10) containing the callback is irrelevant.

  • Line 13: Registering the callback with the correct filename works.
  • Line 13: (Bonus) register_deactivation_hook works too.

I’ve left the rest of the code in place so that you can compare my additions linewise with the original register_activation_hook example.

Callbacks in different file

Now we need to take a look at the code in my_other_file.php. Having these functions in a different file is irrelevant for a plugin this small, but it does serve a useful purpose for testing. For larger applications, separating important parts of the code is an important principle of software design.

1
2
3
4
5
6
7
8
9
10
11
<?php
/* Callback for activation hook */
function my_other_function() {
	add_option('activation1','Activated');
}
 
/* Callback for deactivation hook */
function clean_em_up() {
	delete_option('activation1');
}
?>

This is easy stuff, the callbacks just add or remove an option in the WordPress options table.

When you run the code presented in these two listings, take a look at your options database, as shown in this screenshot:

register_activation_hook test using options database

register_activation_hook test using options database


There’s other ways to check, but this is pretty fast, and if you aren’t familiar with the options table you need to be.

Why is register_activation_hook so hard?

I can’t speak for everyone, but here’s what I think:

  • PHP variable scoping rules feel kooky coming from a C/C++/Java background. PHP looks like C, smells like C, but doesn’t really walk like C. Trouble comes when programmers absent-mindedly crank out PHP code, unaware of the differences in scoping rules.
  • Callbacks give people trouble, even these activation/deactivation functions which are so simple they don’t even take arguments.
  • Man pages are inaccessibly written, and often out of date. But manual should be the first place to start. If the manual has test code, run it to check it’s accuracy.
  • Even fewer people read the code. The comments for register_activation_hook are crystal clear about what’s expected. If only people would read the source!

You should probably jump over to Reverse Engineering Activation Hook In WordPress Plugin API for more information. This is not really a series of articles… yet. Although I do have at least a couple more articles to write on register_activation_hook. Maybe three or four more. At the end of the last article (that is, when I get tired of writing them), I’ll give you a two-step procedure ensuring you will never, ever have trouble with this function again.


Ok, enough preaching… here’s something for you scanners…

What’s in it for me?

More work, if you’re so inclined. But this is good work. Your work.

Here’s the deal. My friend Deacon and I have a long running discussion on deliberate practice. We both crave personal and professional excellence, and we believe that the path to mastery is in the practice of mastery. Deacon cuts wood blocks. I cut code.

masteryPart of our inspiration comes from this little book, George Leonard’s Mastery. In about 100 small pages, Leonard lays out how mastery is achieved through practice. Practice in the sense of “doing what you do” on a regular basis, with deep concentration.

Practice puts the journey first.

The means become the ends.

Here, taking on some silly misconceptions about some random WordPress function is not what’s important.

Instead, the process of examining the problem, understanding why the problem exists, and constructing an elegant solution is my path to mastery.

I don’t care about register_activation_hook. I care about:

  1. Understanding WordPress coding conventions. Understanding this code helps me “get inside the developer’s heads.” I want to think how they think. That’s when the “programming” ends… and the creativity begins.
  2. Learning PHP behavior, specifically, variable scoping rules. Same as above: practice the programming so I don’t have to think about it.
  3. Ensuring my plugins work correctly when I need to invoke the activation hook. I have a legitimate need to understand how this function works.
  4. And… (long time readers know what’s coming) smacking down an under-served keyword. Actually, two. An hour of free blog post engineering to the first person who guesses my second keyword.

Learning the intricacies of register_activation_hook is just the convenient vehicle carrying me further along my path.

What’s your path to mastery?

Do you have a regular practice? If so, tell us about it!

Comments

  1. You know way more about WordPress than I ever should. You make my brain hurt some days. I will just hire you when I have issues that I can’t figure out OK?
    Later
    Justin
    .-= Justin Matthews´s last blog ..If Only My Blog Was A Fish. =-.

  2. Deacon says:

    People might start to catch on what my recent woodblock prints are *really* about ;)

    The post I’m working on for later today spills the beans that there is more to it than skateboards and punk rock.
    .-= Deacon´s last blog ..Poser Skates and Woodblock Prints =-.

  3. Dave Doolin says:

    Stats are really interesting this morning: zero traffic to any “human interest” articles.

    Every single hit this morning is on technical articles.

    Today might be low traffic as many readers will be repelled by the technical content. I’ll make it up in the long term with search results.
    .-= Dave Doolin´s last blog ..How Julie Became a Published Writer (And you can, too) =-.

  4. As one of your non-technical readers you made my brain hurt a little ;) The funny thing is, as much as I will moan if my husband tries to set something up without reading the man-pages (hehehe, that phrase made me giggle!) because it invariably goes wrong and then I feel duty bound to offer helpful suggestions, aside from all that, I can totally relate to tinkering when it comes to code.

    You’re way past my understanding. I only just got to the point where I can use the thesis hooks to do what I want to. But I do equally get where you’re coming from.

    As for your deliberate practice thing, it sounds like what I do when I call this life a game. If it’s just about getting from A to B, where’s the fun in that? It’s all about the journey. So different vocabulary but I’m with you.
    .-= Eleanor Edwards´s last blog ..Legislation for a weapon? You can help! =-.

  5. Ralph says:

    Dave,
    I was excited to see this post and hoping that it might say something at a level I was prepared to engage. TMI. I guess I am resigned to becoming more successful and hiring an expert to make things work right but then you tell me that the ‘experts’ get it wrong too.

    • Dave Doolin says:

      Ralph, engage on the level of “practice.”

      Find out what those things are you need to master, then practice those things. Over and over again.

      Constructing repeatable code is something I need to do on a regular basis. That’s my practice.

      Your practice will be different.

      Also, I’m not an expert in any sense of the word. We’re going through a big social backlash against “experts,” and truly, I am not an expert on WordPress. I am however, competent to employ this function in a plugin!

      Experts do get it wrong a lot. They’re just supposed to be aware of it when they do get it wrong.

      Just so you know, this article and the previous article represent at least 40 hours of my time, taken over several months. Acquiring in-depth knowledge is time consuming.

      .-= Dave Doolin´s last blog ..Caressing Alien Species, and, a (late) Valentine… Take cover! It’s two Weeks in Review =-.

  6. I know I’m reading this after the second one, but it makes more sense to me in this order!

    Is “activation1.php” the name of your main plugin code file? Because in the deconstruction you say that activation hook [sic?] operates on the plugin name but “activation1.php” is not the plugin name – the code and your comments both say the plug name is “A Test”.

    At first I thought you had accidentally switched from using “activation1.php” and “my_other_file.php” to name the second file, but that makes even less sense.

    And if the plugin name is “A Test” then won’t WordPress go looking for a_test.php as the main code file? I was under the (mis?)impression that the main code file needed to match the plugin name for some code-related reason aside from “it’s easier for the programmer to remember”.

    Clarification, please Sir!

    About deliberate practice – I guess my practice is simply in constructing and refining my websites (and reading these articles), which is deliberately done as PHP practice as well as as website construction. On the other hand it’s not deliberate in terms of “I shall learn a, then b, then c” being deliberately decided in advance. I have been learning PHP piecemeal as I need to figure out how to make WordPress do more and more, rather than in a more coherent fashion. Does this count as deliberate practice in your book? I’m getting better at it, so it works for me.

    PS
    Ranking keywords – in my google searches (which default to google.com.au, just to complicate matters) you’re ranking on ‘register_activation_hook’ (7th) and ‘register_deactivation_hook’ (28th), so I’m guessing that’s the second one you optimised for. Others I suspected were:
    George Leonard’s Mastery
    practice of mastery
    deliberate practice
    None of them ranked in the top 100 in my Google search. I evidently underestimated the popularity of these topics because it’s not a book or a phrase I’ve come across before. I may also admit to checking “man pages” but mostly to see what it returned – I am utterly unsurprised that you don’t rank in the top 100 for that one!!
    .-= Ricky Buchanan´s last blog ..Accessibility and the iPad: First Impressions =-.

    • Dave Doolin says:

      Hehe… everything become crystal clear next week, when I conclude this series of articles.

      Deliberate practice: you have it right with the notion of “Learn A, B and C” in that order and practice until you don’t have to think about it.

      There’s much more coming on this. Watch Deacon too, we’re ping-ponging the discussion between our blogs.
      .-= Dave Doolin´s last blog ..WordPress Plugin Activation using PHP classes =-.

Trackbacks

  1. [...] of you that read Dave regularly got a hint today though) Share and [...]

Speak Your Mind

*

CommentLuv badge