Лучший способ позволить плагины для приложения PHP

Попробуйте поместить document.getElementById в setTimeout()

Например.

setTimeout(function(){
    console.log(document.getElementById('whatever'));
}, 100);

Если это сработает, тогда это просто проблема синхронизации.

267
задан Abdulla Nilam 14 December 2015 в 10:05
поделиться

7 ответов

Вы могли использовать Шаблон "наблюдатель". Простой функциональный способ выполнить это:

<?php

/** Plugin system **/

$listeners = array();

/* Create an entry point for plugins */
function hook() {
    global $listeners;

    $num_args = func_num_args();
    $args = func_get_args();

    if($num_args < 2)
        trigger_error("Insufficient arguments", E_USER_ERROR);

    // Hook name should always be first argument
    $hook_name = array_shift($args);

    if(!isset($listeners[$hook_name]))
        return; // No plugins have registered this hook

    foreach($listeners[$hook_name] as $func) {
        $args = $func($args); 
    }
    return $args;
}

/* Attach a function to a hook */
function add_listener($hook, $function_name) {
    global $listeners;
    $listeners[$hook][] = $function_name;
}

/////////////////////////

/** Sample Plugin **/
add_listener('a_b', 'my_plugin_func1');
add_listener('str', 'my_plugin_func2');

function my_plugin_func1($args) {
    return array(4, 5);
}

function my_plugin_func2($args) {
    return str_replace('sample', 'CRAZY', $args[0]);
}

/////////////////////////

/** Sample Application **/

$a = 1;
$b = 2;

list($a, $b) = hook('a_b', $a, $b);

$str  = "This is my sample application\n";
$str .= "$a + $b = ".($a+$b)."\n";
$str .= "$a * $b = ".($a*$b)."\n";

$str = hook('str', $str);
echo $str;
?>

Вывод:

This is my CRAZY application
4 + 5 = 9
4 * 5 = 20

Примечания:

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

Это - всего один метод выполнения сменной системы в PHP. Существуют лучшие альтернативы, я предлагаю, чтобы Вы проверили Документацию WordPress для получения дополнительной информации.

Извините, кажется, что символы подчеркивания заменяются объектами HTML Скидкой с цены? Я могу повторно отправить этот код, когда эта ошибка исправлена.

Редактирование: Nevermind, только кажется, что путь, когда Вы редактируете

157
ответ дан 2 revs, 2 users 86% 23 November 2019 в 02:24
поделиться

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

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

+1 к kdeloach от меня.

34
ответ дан w-ll 23 November 2019 в 02:24
поделиться

Вот подход, который я использовал, это - попытка скопировать со спокойного механизма сигналов/слотов, своего рода Шаблона "наблюдатель". Объекты могут испустить сигналы. Каждый сигнал имеет идентификатор в системе - это составлено идентификатором отправителя + имя объекта, Каждый сигнал может быть связан с получателями, который просто является "вызываемым", Вы используете класс шины, чтобы передать сигналы кому-либо заинтересованному получением их, Когда что-то происходит, Вы "отправляете" сигнал. Ниже и реализация в качестве примера

    <?php

class SignalsHandler {


    /**
     * hash of senders/signals to slots
     *
     * @var array
     */
    private static $connections = array();


    /**
     * current sender
     *
     * @var class|object
     */
    private static $sender;


    /**
     * connects an object/signal with a slot
     *
     * @param class|object $sender
     * @param string $signal
     * @param callable $slot
     */
    public static function connect($sender, $signal, $slot) {
        if (is_object($sender)) {
            self::$connections[spl_object_hash($sender)][$signal][] = $slot;
        }
        else {
            self::$connections[md5($sender)][$signal][] = $slot;
        }
    }


    /**
     * sends a signal, so all connected slots are called
     *
     * @param class|object $sender
     * @param string $signal
     * @param array $params
     */
    public static function signal($sender, $signal, $params = array()) {
        self::$sender = $sender;
        if (is_object($sender)) {
            if ( ! isset(self::$connections[spl_object_hash($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[spl_object_hash($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }

        }
        else {
            if ( ! isset(self::$connections[md5($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[md5($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }
        }

        self::$sender = null;
    }


    /**
     * returns a current signal sender
     *
     * @return class|object
     */
    public static function sender() {
        return self::$sender;
    }

}   

class User {

    public function login() {
        /**
         * try to login
         */
        if ( ! $logged ) {
            SignalsHandler::signal(this, 'loginFailed', 'login failed - username not valid' );
        }
    }

}

class App {
    public static function onFailedLogin($message) {
        print $message;
    }
}


$user = new User();
SignalsHandler::connect($user, 'loginFailed', array($Log, 'writeLog'));
SignalsHandler::connect($user, 'loginFailed', array('App', 'onFailedLogin'));

$user->login();

?>
23
ответ дан mauris 23 November 2019 в 02:24
поделиться

Я полагаю, что самый легкий путь состоял бы в том, чтобы последовать собственному совету Jeff и взглянуть вокруг существующего кода. Попытайтесь смотреть на Wordpress, Drupal, Joomla и другой известный основанный на PHP CMS, чтобы видеть, как их API сцепляет стиль. Таким образом, можно даже получить идеи, о которых Вы не могли думать ранее для создания вещей немного большим количеством rubust.

А более прямой ответ должен был бы записать общие файлы, что они будут "include_once" в свой файл, который обеспечил бы удобство использования, в котором они будут нуждаться. Это было бы разбито в категории и НЕ обеспечено в одном КРУПНОМ "hooks.php" файле. Будьте осторожны, хотя, потому что, что заканчивает тем, что произошло, то, что файлы, которые они включают, заканчивают тем, что имели все больше зависимостей, и функциональность улучшается. Попытайтесь поддержать зависимости от API на низком уровне. Т.Е. меньше файлов для них для включения.

17
ответ дан helloandre 23 November 2019 в 02:24
поделиться

Существует аккуратный проект, названный Колюшка Matt Zandstra в Yahoo, который обрабатывает большую часть работы для обработки плагинов в PHP.

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

архитектора PHP
15
ответ дан Peter Mortensen 23 November 2019 в 02:24
поделиться

Хороший совет состоит в том, чтобы посмотреть, как другие проекты сделали его. Многие призывают к установке плагинов, и их "имя", зарегистрированное для сервисов (как Wordpress, делает), таким образом, у Вас есть "точки" в Вашем коде, где Вы вызываете функцию, которая идентифицирует зарегистрированных слушателей и выполняет их. Стандартная скороговорка дизайна OO Шаблон "наблюдатель" , который был бы хорошим вариантом реализовать в действительно объектно-ориентированной системе PHP.

Платформа Зенда использует много методов сцепления и очень приятно проектируется. Это было бы хорошей системой для взгляда на.

11
ответ дан THEMike 23 November 2019 в 02:24
поделиться

Итак, допустим, вам не нужен шаблон «Наблюдатель», потому что он требует, чтобы вы изменили методы вашего класса для обработки задачи прослушивания и хотите чего-то общего. Допустим, вы не хотите использовать наследование extends , потому что вы уже можете наследовать в своем классе от другого класса. Разве не было бы замечательно иметь общий способ сделать любой класс подключаемым без особых усилий ? Вот как это сделать:

<?php

////////////////////
// PART 1
////////////////////

class Plugin {

    private $_RefObject;
    private $_Class = '';

    public function __construct(&$RefObject) {
        $this->_Class = get_class(&$RefObject);
        $this->_RefObject = $RefObject;
    }

    public function __set($sProperty,$mixed) {
        $sPlugin = $this->_Class . '_' . $sProperty . '_setEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        $this->_RefObject->$sProperty = $mixed;
    }

    public function __get($sProperty) {
        $asItems = (array) $this->_RefObject;
        $mixed = $asItems[$sProperty];
        $sPlugin = $this->_Class . '_' . $sProperty . '_getEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        return $mixed;
    }

    public function __call($sMethod,$mixed) {
        $sPlugin = $this->_Class . '_' .  $sMethod . '_beforeEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }
        if ($mixed != 'BLOCK_EVENT') {
            call_user_func_array(array(&$this->_RefObject, $sMethod), $mixed);
            $sPlugin = $this->_Class . '_' . $sMethod . '_afterEvent';
            if (is_callable($sPlugin)) {
                call_user_func_array($sPlugin, $mixed);
            }       
        } 
    }

} //end class Plugin

class Pluggable extends Plugin {
} //end class Pluggable

////////////////////
// PART 2
////////////////////

class Dog {

    public $Name = '';

    public function bark(&$sHow) {
        echo "$sHow<br />\n";
    }

    public function sayName() {
        echo "<br />\nMy Name is: " . $this->Name . "<br />\n";
    }


} //end class Dog

$Dog = new Dog();

////////////////////
// PART 3
////////////////////

$PDog = new Pluggable($Dog);

function Dog_bark_beforeEvent(&$mixed) {
    $mixed = 'Woof'; // Override saying 'meow' with 'Woof'
    //$mixed = 'BLOCK_EVENT'; // if you want to block the event
    return $mixed;
}

function Dog_bark_afterEvent(&$mixed) {
    echo $mixed; // show the override
}

function Dog_Name_setEvent(&$mixed) {
    $mixed = 'Coco'; // override 'Fido' with 'Coco'
    return $mixed;
}

function Dog_Name_getEvent(&$mixed) {
    $mixed = 'Different'; // override 'Coco' with 'Different'
    return $mixed;
}

////////////////////
// PART 4
////////////////////

$PDog->Name = 'Fido';
$PDog->Bark('meow');
$PDog->SayName();
echo 'My New Name is: ' . $PDog->Name;

В части 1 это то, что вы можете включить с помощью вызова require_once () в верхней части вашего PHP-скрипта. Он загружает классы, чтобы сделать что-то подключаемым.

В Части 2 мы загружаем класс именно сюда. Обратите внимание, что мне не нужно было делать ничего особенного с классом, который значительно отличается от шаблона Observer.

В Части 3 это ' s, где мы переключаем наш класс на «подключаемый» (то есть поддерживающий плагины, которые позволяют нам переопределять методы и свойства класса). Так, например, если у вас есть веб-приложение, у вас может быть реестр плагинов, и вы можете активировать их здесь. Также обратите внимание на функцию Dog_bark_beforeEvent () . Если я установлю $ mixed = 'BLOCK_EVENT' перед оператором return, он заблокирует лай собаки, а также заблокирует событие Dog_bark_afterEvent, потому что не будет никакого события.

В части 4 это код нормальной работы, но обратите внимание, что то, что вы могли подумать, работает совсем не так. Например, собака объявляет свое имя не «Фидо», а «Коко». Собака говорит не «мяу», а «гав». И когда ты хочешь посмотреть на собаку ' После этого вы обнаружите, что это «Другой», а не «Коко». Все эти переопределения были предоставлены в Части 3.

Итак, как это работает? Что ж, давайте исключим eval () (который все называют «злом») и исключим, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

вместо «Коко». Все эти переопределения были предоставлены в Части 3.

Итак, как это работает? Что ж, давайте исключим eval () (который все называют «злом») и исключим, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

вместо «Коко». Все эти переопределения были предоставлены в Части 3.

Итак, как это работает? Что ж, давайте исключим eval () (который все называют «злом») и исключим, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

s исключают eval () (который все называют «злом») и исключают, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

s исключают eval () (который все называют «злом») и исключают, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)

57
ответ дан 23 November 2019 в 02:24
поделиться
Другие вопросы по тегам:

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