I'm busy writing my first plugin, using PHP 5.3.5. I come from a C# environment, and I must say I'm more than happy with the level of support for good, solid OOP techniques in PHP. However, I'm a little uncertain how to structure a plugin using classes. I have a plugin class that takes care of hook registration in its constructor, and some worker classes like a mail queue and mailer, but I have one or two non-class scripts, mostly for forms, that I don't quite know how to neatly fit into classes. What resources are their I can consult for guidance on this aspect of my OO plugin?

The plugin is for mass mailing, i.e. mailing to all subscribers, on schedule etc. It registers a custom post type for mail templates, with add new and edit capabilities, and it adds its own menu to the bottom of the admin menu, currently with two submenu pages: 'settings' and 'send mail'. It also adds an 'opt out' option to the user profile page, but that's quite tidy and easy to include the main plugin class.

  • 1
    It's hard to give an exact answer without seeing the code you want to refactor, or at least having an idea of how it looks like.
    – scribu
    Commented Oct 28, 2011 at 16:43
  • @scribu, I have added a basic description of the plugin. It isn't practical to include all my code here.
    – ProfK
    Commented Oct 28, 2011 at 17:12

2 Answers 2


I have one or two non-class scripts, mostly for forms, that I don't quite know how to neatly fit into classes.

Split your project into multiple classes. Keep your worker classes as instantiable objects (typical OOP patterns) and put your non-class scripts into a class of their own as static scripts.

I often use static PHP classes to namespace my code this way. Example:

class My_Object {
    public $variable = 1;

    public function __construct() {
        // Constructor

    public function do_something() {
        // Misc. method for the object

static class Helper {
    public static function Run_Script() {
        // Function that does something and doesn't belong in a class

The difference between these two classes is that you instantiate one (My_Object) and use it as an object. The other is basically a namespace wrapper for a function that doesn't belong in an object but that also doesn't belong in the global namespace.

Let's say you started with just a regular Run_Script() method in your plugin ... then later down the road, another developer adds a Run_Script() method to another plugin. You now have a name conflict. Keeping your standalone functions inside a static class helps prevent this.

Just call Helper::Run_Script() to access it.

What resources are there I can consult for guidance on this aspect of my OO plugin?

Basically, look at what others have done. There are quite a few quality plugins out there that follow this kind of a pattern. So take a look at how others have tackled the problem and learn from their example.

GitHub is a great place to look at code. Most of my plugins are up there, so you can browse through code files to view the structure without needing to download them and install them.

Some good developers on GitHub that you should follow for more examples:

  • Is creating a class merely to avoid potential naming collisions good practice? There must be an alternative, maybe just use a unique prefix? Or is there another benefit to having the function as part of a class? Commented Mar 3, 2015 at 19:27
  • There are two alternatives: function prefixing (meaning everything starts with my_unique_prefix_) or real PHP namespaces. The former works but is bulky, inflexible, and leads to incredibly ugly and hard-to-maintain/reuse-across-projects code. The latter only works if you're dropping WordPress' default PHP 5.2 backwards compatibility.
    – EAMann
    Commented Mar 4, 2015 at 5:15
  • Thanks for replying. 5.2 is currently used by 16.6% of WordPress websites according to these stats. Probably explains why the namespace feature hasn't been used by many yet. Commented Mar 4, 2015 at 10:57
class Plugin{
    static public function Construct(){
        static $single_call = false; // Enable calling this just once
        if($single_call) return; // Skip double hooking
        add_filter('the_content', array(__CLASS__, 'TheContent'));
        $single_call = true; // Block future calls
     * @internal
    static private function ContentModifier($content){
        return $content;
    // All actions/filters must be public, internal methods can stay private
    static public function TheContent($content){
        return self::ContentModifier($content);
Plugin::Construct(); // Single Call

Create static classes for plugins. Actions/Filters must be public.

And, as you use PHP 5.3+, consider Closures where you need single-use hard to remove actions/filters.

add_filter('the_content', function($content){
    return $content;

I come from C++, welcome to PHP!

  • 2
    It's confusing to call a static method 'Construct'. Also, it doesn't really answer the OP's question.
    – scribu
    Commented Oct 28, 2011 at 15:42
  • @scribu Why that? Why would you create the plugin structure as a non-static class. Why would you want users to randomly instantiate your object and keep adding layers of actions/filters... Eu evit clasele pt. pluginuri de obicei, dar in afara de Widget-uri, sunt statice! Commented Oct 28, 2011 at 15:49
  • And I do think I answered the question. Read his question. He instantiates in constructor. Really bad. Static methods should be used to ensure single addition of actions/filters. He also want to add external functions to a class. Static is also the way to go... Commented Oct 28, 2011 at 15:52
  • 2
    Hold on. I'm all for static methods. I was just saying that 'Construct' is a bad name for that method, since it resembles '__construct()'.
    – scribu
    Commented Oct 28, 2011 at 16:28
  • 2
    +1 @scribu. Use __construct() or create a static function like initialize(). Also, FWIW, lower-case your class methods. Since this is a WordPress specific SE, check out the WordPress Coding Standards in the Codex: codex.wordpress.org/WordPress_Coding_Standards.
    – Tom Auger
    Commented Oct 28, 2011 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.