Вопрос или проблема
В настоящее время я пытаюсь создать плагин для WordPress для создания страницы настроек. Но по какой-то причине, когда я использую add_action("admin_init", array(class_object, 'function_name'))
, функция add_action выполняется, но не доходит до обратного вызова. Она просто пропускает его.
Я попробовал создать тестовый класс с одной функцией так же, как в основном классе, и это работает. Значит, я делаю что-то не так где-то, но не знаю, что именно.
Вот код. Я разделил код на 3 разных файла, и я размещу его в порядке включения файлов.
Файл индекса для плагина
include('admin/options.php');
function social_share_menu_item() {
add_submenu_page("options-general.php", "Social Share", "Social Share", "manage_options", "social-share", 'socialShareOptions');
}
add_action("admin_menu", "social_share_menu_item");
...
options.php
include_once('settings/SocialOptions.class.php');
function socialShareOptions(){
$options = array(
array(
'type' => 'checkbox',
'name' => 'social-share-facebook',
'value' => 1,
'title' => 'Показать Facebook '
),
array(
'type' => 'checkbox',
'name' => 'social-share-twitter',
'value' => 1,
'title' => 'Показать Twitter'
),
array(
'type' => 'checkbox',
'name' => 'social-share-instagram',
'value' => 1,
'title' => 'Показать Instagram'
)
);
$socialOptions = new SocialOptions($options);
$socialOptions->buildSettingsPage();
add_action("admin_init", array($socialOptions, 'setOptions') );
}
SocialOptions.class.php
class SocialOptions {
private $_optionsArray;
function __construct( $options = array() ) {
$this->_optionsArray = $options;
}
public function setOptions() {
add_settings_section("social_share_config_section", "", null, "social-share");
foreach ( $this->_optionsArray as $option) {
add_settings_field("social-share-facebook", $option['title'], array($this, 'option'), "social-share", "social_share_config_section", $option);
}
foreach ( $this->_optionsArray as $option) {
register_setting("social_share_config_section", $option['name']);
}
}
public function option( $fieldData ){
?>
<input type="<?php echo $fieldData['type'] ?> " name="<?php echo $fieldData['name']; ?>" value="<?php echo $fieldData['value'] ?>"<?php checked(1, get_option($fieldData['name']), true)?> /><?php echo $fieldData['title'] ?>
<?php
}
public function buildSettingsPage() {
$html="<div class="wrap social-admin-style">
<div class="title">
<h1>Настройки социального обмена</h1>
</div>
<div class="main-content">
<form method="post" action="options.php">
" . settings_fields("social_share_config_section") . '
' . do_settings_sections("social-share") . '
'. submit_button() . '
</form>
</div>
</div>';
echo $html;
}
}
Как уже упоминалось, при отладке кода я вижу, что функция add_action выполняется, но в какой-то момент она просто пропускает конец функции и никогда не заходит в метод setOptions.
Когда я создаю следующее, все работает нормально:
options.php
include_once('settings/SocialOptions.class.php');
class Test {
function testing(){
return 'ничего';
}
}
function socialShareOptions(){
$options = array(
...
);
$socialOptions = new SocialOptions($options);
$socialOptions->buildSettingsPage();
/*ОБРАТИТЕ ВНИМАНИЕ НА ЭТУ ЧАСТЬ*/
$test = new Test();
add_action("admin_init", array($test, 'testing') );
}
Это выполнится в отладке нормально. Вот почему я не понимаю, почему другой метод не работает.
Дополнительная информация
подсказано B. Schuiling
В php error logs я не вижу никаких ошибок.
Надеюсь, вы сможете помочь. Спасибо, что уделили время для чтения этого. Если вам нужна дополнительная информация, пожалуйста, дайте мне знать.
ИЗМЕНЕНИЕ
Хотя первоначальный ответ не указывал на причину проблемы, я хотел бы, чтобы вы все ссылались на ответ B. Schuiling. В комментариях он объяснил, что add_action был вызван слишком поздно и поэтому не выполнялся.
Ниже приведена измененная страница options.php (я пропустил очевидный код, чтобы сократить объем).
пс хотя это работает, я собираюсь изменить код на синглтон. Это также основано на ссылке, которую B. Schuiling разместил в комментариях к своему собственному ответу ниже.
Обратите внимание, что массив опций и инстанцирование класса теперь вне функции socialShareOptions.
include_once('settings/SocialOptions.class.php');
$options = array(
...
)
);
$socialOptions = new SocialOptions($options);
add_action("admin_init", array($socialOptions, 'setOptions'));
function socialShareOptions(){
global $socialOptions;
$socialOptions->buildSettingsPage();
}
В вашем классе ваша функция называется ‘public function setOption()’, а не setOptionS. Проверьте свой лог ошибок на предмет подобных проблем.
Также в вашем коде я не вижу, чтобы функция ‘socialShareOptions’ на самом деле вызывалась где-либо.
Ответ или решение
Диагностика проблемы: add_action
не вызывает функцию обратного вызова
В процессе разработки плагина для WordPress может возникнуть проблема, когда функция обратного вызова, назначенная с помощью add_action
, не вызывается, даже если add_action
сам по себе выполняется. Давайте подробно разберем вашу ситуацию, чтобы установить причину и предложить решение.
Описание проблемы
Вы столкнулись с тем, что функция setOptions
вашего класса SocialOptions
не вызывается в результате выполнения действия admin_init
. Вместо этого WordPress просто пропускает выполнение этой функции. Данная проблема часто связана с порядком вызова и временем выполнения ваших функций относительно хуков WordPress.
Пример кода
Ваш код состоит из трех частей: основного файла плагина, файла options.php
и файла класса SocialOptions.class.php
. Это создает определенную структуру для добавления элементов на страницу настроек, но неявные проблемы могут возникнуть из-за некоторых нюансов.
Анализ имеющегося кода
-
Функция
socialShareOptions()
:- Вы добавляете действие
add_action("admin_init", array($socialOptions, 'setOptions'));
внутри функцииsocialShareOptions()
. - Однако функция
socialShareOptions
не вызывается по умолчанию, что может привести к тому, что действиеadmin_init
вообще не выполнится, и, следовательно, ваша функцияsetOptions
не будет вызвана.
- Вы добавляете действие
-
Проблема с порядком выполнения:
add_action
должен быть вызван до того, как работа с хуками начнется. Если в момент добавления действия WordPress уже инициировал хукadmin_init
, ваша функция не будет зарегистрирована. В вашем случае функцияsetOptions
не будет вызвана, поскольку добавление действия осуществляется только после вызоваsocialShareOptions()
.
Решение проблемы
Для исправления кода рекомендуется вынести добавление действия add_action
из функции socialShareOptions()
, чтобы оно вызывалось на этапе инициализации, а не тогда, когда обрабатывается функция отображения страницы настроек.
Модифицированный код options.php
:
include_once('settings/SocialOptions.class.php');
// Определяем массив опций
$options = array(
array(
'type' => 'checkbox',
'name' => 'social-share-facebook',
'value' => 1,
'title' => 'Показать Facebook'
),
array(
'type' => 'checkbox',
'name' => 'social-share-twitter',
'value' => 1,
'title' => 'Показать Twitter'
),
array(
'type' => 'checkbox',
'name' => 'social-share-instagram',
'value' => 1,
'title' => 'Показать Instagram'
)
);
// Создаем экземпляр класса вне функции
$socialOptions = new SocialOptions($options);
// Добавляем действие на admin_init до вызова socialShareOptions
add_action("admin_init", array($socialOptions, 'setOptions'));
function socialShareOptions() {
global $socialOptions;
$socialOptions->buildSettingsPage();
}
Вывод
Ключевой аспект, который необходимо помнить — это порядок выполнения и инициализации ваших функций и хуков в WordPress. Если функция, к которой вы хотите обратиться, вызывается внутри другой функции, то сначала убедитесь, что первая функция будет вызвана. Как вы и заметили, исходная проблема заключалась в том, что действие добавлялось слишком поздно в цепочке вызовов.
Переход к паттерну с синглтоном, как вы упомянули, также может быть полезным для улучшения управления экземплярами классов и повышения читаемости кода.
Если будут возникать дополнительные вопросы или сложности, не стесняйтесь обращаться за помощью. Удачи в развитии вашего плагина!