Попробуйте поместить document.getElementById
в setTimeout()
Например.
setTimeout(function(){
console.log(document.getElementById('whatever'));
}, 100);
Если это сработает, тогда это просто проблема синхронизации.
Вы могли использовать Шаблон "наблюдатель". Простой функциональный способ выполнить это:
<?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, только кажется, что путь, когда Вы редактируете
рычаг и слушатель метод обычно используется, но существуют другие вещи, которые можно сделать. В зависимости от размера Вашего приложения, и то, кто Ваша попытка позволить видит код (эта попытка быть сценарием FOSS или чем-то в доме), будет влиять значительно, как Вы хотите позволить плагины.
kdeloach имеет хороший пример, но его функция реализации и рычага немного небезопасна. Я попросил бы Вас давать больше информации природы php приложения Ваша запись, И как Вы видите, что плагины вписываются.
+1 к kdeloach от меня.
Вот подход, который я использовал, это - попытка скопировать со спокойного механизма сигналов/слотов, своего рода Шаблона "наблюдатель". Объекты могут испустить сигналы. Каждый сигнал имеет идентификатор в системе - это составлено идентификатором отправителя + имя объекта, Каждый сигнал может быть связан с получателями, который просто является "вызываемым", Вы используете класс шины, чтобы передать сигналы кому-либо заинтересованному получением их, Когда что-то происходит, Вы "отправляете" сигнал. Ниже и реализация в качестве примера
<?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();
?>
Я полагаю, что самый легкий путь состоял бы в том, чтобы последовать собственному совету Jeff и взглянуть вокруг существующего кода. Попытайтесь смотреть на Wordpress, Drupal, Joomla и другой известный основанный на PHP CMS, чтобы видеть, как их API сцепляет стиль. Таким образом, можно даже получить идеи, о которых Вы не могли думать ранее для создания вещей немного большим количеством rubust.
А более прямой ответ должен был бы записать общие файлы, что они будут "include_once" в свой файл, который обеспечил бы удобство использования, в котором они будут нуждаться. Это было бы разбито в категории и НЕ обеспечено в одном КРУПНОМ "hooks.php" файле. Будьте осторожны, хотя, потому что, что заканчивает тем, что произошло, то, что файлы, которые они включают, заканчивают тем, что имели все больше зависимостей, и функциональность улучшается. Попытайтесь поддержать зависимости от API на низком уровне. Т.Е. меньше файлов для них для включения.
Существует аккуратный проект, названный Колюшка Matt Zandstra в Yahoo, который обрабатывает большую часть работы для обработки плагинов в PHP.
Это осуществляет интерфейс сменного класса, поддерживает интерфейс командной строки и не слишком твердо встать и работающий - особенно при чтении темы номера об этом в журнал .
архитектора PHPХороший совет состоит в том, чтобы посмотреть, как другие проекты сделали его. Многие призывают к установке плагинов, и их "имя", зарегистрированное для сервисов (как Wordpress, делает), таким образом, у Вас есть "точки" в Вашем коде, где Вы вызываете функцию, которая идентифицирует зарегистрированных слушателей и выполняет их. Стандартная скороговорка дизайна OO Шаблон "наблюдатель" , который был бы хорошим вариантом реализовать в действительно объектно-ориентированной системе PHP.
Платформа Зенда использует много методов сцепления и очень приятно проектируется. Это было бы хорошей системой для взгляда на.
Итак, допустим, вам не нужен шаблон «Наблюдатель», потому что он требует, чтобы вы изменили методы вашего класса для обработки задачи прослушивания и хотите чего-то общего. Допустим, вы не хотите использовать наследование 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 за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)
Итак, как это работает? Что ж, давайте исключим eval ()
(который все называют «злом») и исключим, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)
Итак, как это работает? Что ж, давайте исключим eval ()
(который все называют «злом») и исключим, что это не шаблон наблюдателя. Таким образом, это работает подлый пустой класс под названием Pluggable, который не содержит методов и свойств, используемых классом Dog. Таким образом, как только это произойдет, нас задействуют магические методы. Вот почему в частях 3 и 4 мы возимся с объектом, производным от класса Pluggable, а не с самим классом Dog. Вместо этого мы позволяем классу Plugin «касаться» объекта Dog за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)
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 за нас. (Если это какой-то шаблон дизайна, о котором я не знаю - дайте мне знать.)