Ссылка add_action класс

Можно ли ссылаться на класс вместо функции в 'add_action'? Кажется, это не понятно. Вот лишь базовый пример рассматриваемой функции.

add_action( 'admin_init', 'MyClass' );
class MyClass {
     function __construct() {
          .. This is where stuff gets done ..
     }
}

Так что да, это не работает. Я также пробовал:

$var = new MyClass();
add_action( 'admin_init', array( &$var ) );

и

$var = new MyClass();
add_action( 'admin_init', array( &$var, '__construct' ) );

А также:

add_action( 'admin_init', 'MyClass::__construct' );

В любом случае я могу сделать это, не создавая отдельную функцию, загружающую класс? Я хотел бы иметь возможность просто запускать конструктор классов через add_action. Это все, что нужно загрузить, чтобы заставить мяч прокатиться.

29 голосов | спросил Matthew Ruddy 5 PMpThu, 05 Apr 2012 17:44:22 +040044Thursday 2012, 17:44:22

7 ответов


53

Нет, вы не можете «инициализировать» или создавать экземпляр класса через крючок, а не напрямую. Требуется некоторый дополнительный код (и это не является желательным, чтобы иметь возможность сделать это, поскольку вы открываете банку червей для себя.

Вот лучший способ сделать это:

class MyClass {
     function __construct() {
          add_action( 'admin_init',array( $this, 'getStuffDone' ) );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();

Конечно, можно было бы создать класс интерфейса, чтобы упростить его для общего случая:

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( 'admin_init',array( $this, 'getStuffDone' ) );
    }
    public abstract function getStuffDone();
}

Обратите внимание, что в качестве интерфейса вы не можете создать объект этого типа напрямую, но вы можете создать подкласс, позволяя вам сказать:

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();

Что бы потом автоматически добавить все крючки, вам просто нужно определить, что именно делается в подклассе, а затем создать его!

В конструкторах

Я бы не добавил конструктор в качестве функции hook, это плохая практика и может привести к множеству необычных событий. Также в большинстве языков конструктор возвращает объект, который создается, поэтому, если ваш крючок должен вернуть что-то вроде фильтра, он не будет возвращать отфильтрованную переменную так, как вы хотите, но вместо этого она вернет объект класса.

Вызов конструктора или деструктора - очень, очень и очень плохая практика программирования, независимо от того, на каком языке вы находитесь, и никогда .

Конструкторы также должны создавать объекты, чтобы инициализировать их, готовые к использованию, а не для реальной работы. Работа, выполняемая объектом, должна выполняться в отдельной функции.

Методы статического класса и вообще не нужно создавать /инициализировать

Если ваш метод класса является методом статического класса, вы можете передать имя класса в кавычках, а не $this, как показано ниже:

class MyClass {
     public static function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
add_action( 'admin_init', array('MyClass','getStuffDone' ) );

Закрытие & PHP 5.3

К сожалению, вы не можете избежать линии, создающей новый класс. Единственное, что можно было бы пропустить, это включить код плиты котла, который все еще имеет эту линию, и потребовал бы PHP 5.3+, например:

add_action('admin_init',function(){
    $var = new MyClass();
    $var->getStuffDone();
});

В этот момент вы также можете пропустить класс и просто использовать функцию:

add_action('admin_init',function(){
    // do stuff
});

Но имейте в виду, что вы теперь представили призрак анонимных функций. Невозможно удалить вышеупомянутое действие с помощью remove_action, и это может и приносит большую боль разработчикам, которые должны работать с кодом других людей.

На амперсандах

Вы можете увидеть действия, используемые следующим образом:

add_action( &$this, 'getStuffDone' );

Плохо . & был добавлен обратно в PHP 4, когда объекты передавались как значения, а не как ссылки. PHP 4 уже более десяти лет и не поддерживается WordPress в течение очень долгого времени.

Существует без причины , чтобы использовать &this при добавлении перехватов и фильтров, а удаление ссылки не вызывает проблем и может даже улучшить совместимость с будущими версиями PHP

Используйте это вместо:

add_action( $this, 'getStuffDone' );
ответил Tom J Nowell 5 PMpThu, 05 Apr 2012 18:16:22 +040016Thursday 2012, 18:16:22
8

Пример класса

Примечания:

  • Инициировать класс только один раз
    • Вызов приоритета 0, поэтому вы можете использовать тот же самый крючок с приоритетом по умолчанию позже
    • Оберните его в ! class_exists, чтобы избежать вызова его дважды и поместить вызывающего объекта внутри
  • Создайте функцию init и класс var static
  • Вызов конструктора изнутри init, когда вы вызываете класс new self.

Вот пример

if ( ! class_exists( 'WPSESampleClass' ) )
{
    // Init the class on priority 0 to avoid adding priority inside the class as default = 10
    add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 );

class WPSESampleClass
{
    /**
     * The Class Object
     */
    static private $class = null;

    public static function init()
    {
        if ( null === self::$class ) 
            self :: $class = new self;

        return self :: $class;
    }

    public function __construct()
    {
        // do stuff like add action calls:
        add_action( 'init', array( $this, 'cb_fn_name' ) );
    }

    public function cb_fn_name()
    {
        // do stuff 
    }
} // END Class WPSESampleClass

} // endif;

Php 5 +

Пожалуйста, , оставьте &. Мы уже за пределами php4. :)

ответил kaiser 5 PMpThu, 05 Apr 2012 18:16:16 +040016Thursday 2012, 18:16:16
1
if (!class_exists("AllInOneWoo")){
    class AllInOneWoo {
        function __construct(){
            add_action('admin_menu', array($this, 'all_in_one_woo') );
        }
        function all_in_one_woo(){
            $page_title = 'All In One Woo';
            $menu_title = 'All In One Woo';
            $capability = 'manage_options';
            $menu_slug  = 'all-in-one-woo-menu';
            $function   = array($this, 'all_in_one_woo_menu');
            $icon_url   = 'dashicons-media-code';
            $position   = 59;

            add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
        }
        function all_in_one_woo_menu(){?>
            <div class="wrap">
                <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1>
            </div>
        <?php }
    }// end class
}// end if

if (class_exists("AllInOneWoo")){       
    $all_in_one_woo = new AllInOneWoo();
}
ответил Zakir Sajib 4 MaramSun, 04 Mar 2018 11:14:23 +03002018-03-04T11:14:23+03:0011 2018, 11:14:23
0

Вы можете запускать события в своем классе, не загружая его изначально . Это удобно, если вы не хотите загружать полный класс вперед, но вам нужно получить доступ к фильтрам и действиям WordPress.

Вот очень простой пример

<?php
class MyClass
{
    public static function init()
    {
        add_filter( 'the_content', array('MyClass', 'myMethod') );
    }

    public static function myMethod($content)
    {
        $content = $content . 'Working without loading the object';
    }
}

MyClass::init();

Это очень упрощенная версия ответа Кайзера, но в простом выражении показывает поведение. Может быть удобен для тех, кто смотрит на этот стиль в первый раз.

Другие методы могут при необходимости инициировать объект. Я лично использую этот метод, чтобы позволить необязательным частям моего плагина вставлять скрипты в очередь, но только запускать объект по запросу AJAX.

ответил John Reid 22 MonEurope/Moscow2014-12-22T17:02:08+03:00Europe/Moscow12bEurope/MoscowMon, 22 Dec 2014 17:02:08 +0300 2014, 17:02:08
0

Это работает для меня:

class foo
{
    public static function bar()
    {
        echo 'it works!';
    }
}

add_action('foo_bar', array('foo', 'bar'));
ответил Jonathan 17 MarpmTue, 17 Mar 2015 21:25:38 +03002015-03-17T21:25:38+03:0009 2015, 21:25:38
0

Вообще говоря, вы не добавили бы целый класс к крюку. Коды add_action() /add_filter() ожидают функции обратного вызова , на которые может ссылаться на внутри класс .

Предположим, что у вас есть класс init() внутри вашего класса, который вы хотите подключить к WordPress init.

Поместите свой add_action() вызов внутри вашего класса, а затем определите обратный вызов следующим образом:

add_action( 'init', array( $this, 'init' ) );

(Примечание. Я предполагаю, что ваш класс правильно размещен на имена, в противном случае обязательно укажите пространства имен ваших функций обратного вызова.)

ответил Chip Bennett 5 PMpThu, 05 Apr 2012 18:03:00 +040003Thursday 2012, 18:03:00
0

Вы должны иметь возможность сделать это, передав имя класса вместо созданного объекта:

add_action( 'init', array( 'MyClass', '__construct' ) );

(Теоретически ваше другое решение должно работать тоже

$var = new MyClass();
add_action( 'admin_init', array( $var, '__construct' ) );

Не уверенный в голове, почему это не так. Может быть, если вы не позвоните по ссылке?)

ответил Boone Gorges 5 PMpThu, 05 Apr 2012 18:09:54 +040009Thursday 2012, 18:09:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132