1
\$\begingroup\$

the last couple of weeks i have been working on my own WordPress plugin. I am trying to do a class based codebase.

My plugin works correctly, but i don't really know if this is the correct way to develop. I would like to learn the best practices.

To demonstrate, here is my base plugin file:


<?php

/**
 * Blub Hamerhaai plugin
 *
 * This is the main blub plugin for all sites
 *
 * @link              {github link}
 * @since             0.0.2
 * @package           Blub Hamerhaai
 *
 * @wordpress-plugin
 * Plugin Name:       {plugin name}
 * Plugin URI:        {github link}
 * Description:       This is the main blub plugin for all sites
 * Version:           0.0.4
 * Author:            Blub
 * Author URI:        {link}
 * License:           Copyright Blub media, all rights reserved
 * License URI:       {link}
 * Text Domain:       blub-hamerhaai
 * Domain Path:       /languages
 *
 * Created by:        Me
 */

namespace Blub;

require 'includes/includes.php';

define(__NAMESPACE__ . '\PLUGINROOT', __FILE__);
define(__NAMESPACE__ . '\PLUGINDIR', __DIR__);

if (!class_exists('Hamerhaai')) {
    class Hamerhaai
    {

        public function __construct()
        {
            register_activation_hook(__FILE__, [$this, 'activation']);
            register_deactivation_hook(__FILE__, [$this, 'deactivation']);
            add_action('init', [$this, 'init']);
        }

        public function activation()
        {
            BlubRole::add();
            PluginUpdate::add();
        }

        public function deactivation()
        {
            BlubRole::remove();
            PluginUpdate::remove();
        }

        public function init()
        {
            //Preventing removals in other pages
            global $pagenow;

            load_textdomain('blub-hamerhaai', PLUGINDIR . '/languages/blub-hamerhaai-nl_NL.mo');

            //Things to do for all users
            new OptionsPage();
            new BlubColors();
            new CustomLoginPage();
            $widget = new DashboardWidget();

            // Things to do for blub user
            if (BlubRole::isBlubUser()) {
                new AdminText();
                new RemoveMenuItems();
                new GutenbergEdits();

                //Only for dashboard
                if ($pagenow === 'index.php') {
                    $widget->forceShow();
                    $widget->removeDefault();
                }

                new LoadFrontendStyle();
            }
        }
    }
}

new Hamerhaai();

The main thing i am insecure about is instantiating all the classes on the plugin init function. I don't think this is the best practice. All the classes are based on a specific functionality.

Can someone explain me if this is the way to go? Or how to improve?

Thanks in advance.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

1. The constructor is not a good place for actions & filters.

See this very detailed answer from WP.SE or this blog post for some reasoning. As far as I understand, it makes testing much more difficult and in a oop-way doesn't make sense, as it doesn't directly relate to the object's state.

2. Do you really need that state?

Right now, your Hamerhaai doesn't actually use state. In this case I usually define the methods as static, which makes enqueue/dequeue much simpler because you don't need the original object.

register_activation_hook(__FILE__, [$this, 'activation']);

// ...
public function activation()
{
    BlubRole::add();
    PluginUpdate::add();
}

would become

register_activation_hook(__FILE__, [__CLASS__, 'activation']);

// ...
public static function activation()
{
    BlubRole::add();
    PluginUpdate::add();
}

(using __CLASS__ simplifies it a lot so you don't need to watch out for namespaces, see PHP Doc)

3. Don't go half the way.

You're doing modern PHP code. So why require 'includes/includes.php';? Use composer's autoloading feature and avoid manual include / require statements. In my plugins, all code lives somewhere in a class. And the class is easily autoloaded via composer.

You're in a namespace, so if (!class_exists('Hamerhaai')) { doesn't actually do what you think it does. Instead you should either check for if (!class_exists('Blub\Hamerhaai')) { or as you're already using __NAMESPACE__ something like

if (!class_exists(__NAMESPACE__ . '\Hamerhaai')) {

4. Only load code that is actually required

        //Things to do for all users
        new OptionsPage();
        new BlubColors();
        new CustomLoginPage();
        $widget = new DashboardWidget();

this code lives in your init() method. So it is called on every request. Most likely you want to check if the user is logged in, has a specific role, etc. before actually calling it.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the feedback! \$\endgroup\$
    – RowanBlub
    Commented Nov 11, 2021 at 9:43

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.