web-dev-qa-db-fra.com

PHP5, Inheritance, Singleton - limitations concernant les hooks de filtre et d'action

Je travaille actuellement sur un plugin, qui utilise la fonctionnalité intégrée cron de wordpress.

Au lieu d'utiliser PHP4, je souhaite utiliser PHP5 avec l'héritage et le modèle de conception singleton. J'ai quelques limitations avec le mécanisme de crochet action et filter et je voulais vous demander si vous avez une autre approche pour résoudre ce problème.

J'ai supprimé toutes les parties non pertinentes de l'exemple de code. Si vous avez besoin du code complet pour la démonstration, merci de poster ici pour que je puisse ajouter un lien pastbin.

Exemple:

Dans la classe de base "Cron", je souhaite déclarer toutes les méthodes, qui décrivent un travail cron. Pour enregistrer une nouvelle entrée cron, j'utilise add_action avec le hookname et une méthode callable.

Le problème:

Pour appeler cette action-hook, la fonction wordpress intégrée do_action a besoin d'un accès extérieur à cette méthode. Pour résoudre le problème, j'ai déclaré la méthode statique publique.

Mais cela ne semble pas juste non plus. La méthode ne devrait pas être accessible de l'extérieur. Cela devrait être privé. Seule la classe MyCron doit avoir l'autorisation d'accéder à cette méthode. J'ai essayé différentes choses comme vous pouvez le voir dans le bloc de commentaires de l'exemple.

Si je déclare le constructeur public (ce qui détruirait le motif singleton), je pourrai définir la méthode sur private. Mais ensuite, chaque fois que j'ajoute un événement, un nouvel objet MyCron est créé.

Aucune suggestion?

Merci, romain


class Cron {
    private $_events;

    protected function __construct() {
        $this->_events = array();
    }

    protected function addEvent($timestamp, $recurrence, $hookname, $hookmethod, $args = array()) {
        $this->_events[] = $hookname;

        if (!wp_next_scheduled($hookname)) {
            wp_schedule_event($timestamp, $recurrence, $hookname, $args);
        }

        add_action($hookname, $hookmethod);
    }
}

class MyCron extends Cron {
    private static $_instance = null;

    public static function getInstance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    protected function __construct() {
        parent::__construct();

        /* Note: 
         * The passing action hook must be public static to be callable from outside. An other option is to declare the constructor
         * public. But this means, everytime I add e new event I will create an new object of MyCron. This is the reason why I
         * the singleton php design pattern with a private/protected constructor.
         * 
         * This doesn't work either:
         * 1) $this->addEvent(time(), 'daily', 'webeo-daily-event', 'MyCron::getInstance->myDailyEvent');
         * 2) $this->addEvent(time(), 'daily', 'webeo-daily-event', 'MyCron::getInstance::myDailyEvent');
         * 3) $this->addEvent(time(), 'daily', 'webeo-daily-event', array('MyCron::getInstance', 'myDailyEvent'));
         * 4) $this->addEvent(time(), 'daily', 'webeo-daily-event', create_function('', 'return MyCron::getInstance()->myDailyEvent();'));
         * 5) $this->addEvent(time(), 'daily', 'webeo-daily-event', function() { return MyCron::getInstance()->myDailyEvent(); });
         */
        $this->addEvent(time(), 'daily', 'webeo-daily-event', array($this, 'myDailyEvent'));

    }

    public static function myDailyEvent() {
        // do this every day with wp cron
    }
}
2
rofflox

Il n'est pas nécessaire de déclarer le constructeur public, mais uniquement la fonction de crochet d'action.

Exemple:

<?php
/*
Plugin Name: Singleton Action
*/

class Singleton_Demo
{
    /**
     * @static $instance Objekt
     * @access private;
     */
    private static $_instance   = NULL;

    protected function __construct() {}
    private final function __clone() {}

    public static function getInstance()
    {
        if ( self::$_instance === NULL )
        {
            self::$_instance = new self;
        }

        return self::$_instance;
    }

    public function hook_test()
    {
        print '<p>Works!</p>';
    }
}

add_action( 'wp_footer', array ( Singleton_Demo::getInstance(), 'hook_test' ) );

De toute façon, je n’utiliserais pas un Singleton. :)

4
fuxia