Исправляем: PHP Fatal error: Call to undefined function wp_get_current_user() на мультисайте

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


Предыстория:

Вначале один пользователь сообщил мне что активировав мое дополнение для WordPress плагина WP-Recall он не может перейти в консоль управления мультисайтом (Управление сетью->Консоль)
Вот сюда:

Ок,

"Какую ошибку выдает на момент перехода? Что в Error.log сервера?"

- ответ был такой:
PHP Fatal error: Uncaught Error: Call to undefined function wp_get_current_user() in our-site.ru/wp-includes/capabilities.php:598

Самая засада в том, что мое дополнение не использует функцию wp_get_current_user. Больше никаких подробностей не сообщалось.
Я свои дополнения не тестировал в работе режима мультисайта и не заявляю о его поддержке (потому что малый процент использование его только лишь добавит мне проблем и траты времени на его тестирование и отладку). Поэтому не придал проблеме должного внимания. Но интересное пошло потом - еще один пользователь сообщил мне о проблеме с 2-мя моими дополнениями. Это было накануне новогодних праздников. Так вот после них я и решил глянуть - в чем проблема. Один репорт - случайность, два - закономерность, а три - это уже проблема. Проблемы должны решаться. Что я и сделал вчера.


Поиск виновного:

Установил на поддомене чистый вордпресс, активировал на нем режим мультисайта, взяв дефолтные настройки сети (каждый новый сайт в подкаталоге).
Активировал проблемный доп и перешел по скрину выше в управление мультисайтом. Белый экран.
Полез в логи и вот что увидел:

PHP Fatal error: Uncaught Error: Call to undefined function wp_get_current_user() in .otshelnik-fm.ru/wp-includes/capabilities.php:598
Stack trace:
# 0 .otshelnik-fm.ru/wp-admin/network/settings.php(16): current_user_can('manage_network_...')
# 1 .otshelnik-fm.ru/wp-content/wp-recall/add-on/hello-private-message/index.php(3): require_once('...')
# 2 .otshelnik-fm.ru/wp-content/plugins/wp-recall/functions/addons.php(96): include_once('...')
# 3 .otshelnik-fm.ru/wp-content/plugins/wp-recall/wp-recall.php(400): rcl_include_addon('...', 'hello-private-m...')
# 4 .otshelnik-fm.ru/wp-content/plugins/wp-recall/wp-recall.php(354): WP_Recall->include_addon('hello-private-m...'
# 5 .otshelnik-fm.ru/wp-content/plugins/wp-recall/wp-recall.php(181): WP_Recall->include_addons()
# 6 .otshelnik-fm.ru/wp-includes/capabilities.php on line 598

wp_get_current_user - эту функцию мой доп не использует, но по стеку видно что add-on/hello-private-message/index.php(3) - в 3-й строке доп подключает файл. Но php скрипт не обрывается, а выполняется дальше. Стек трейс мой доп упомянул - значит косвенно он участвует в падении.

Смотрим, что в 3-й строке:
require_once('settings.php'); - и всё!
WTF? Почему подключая файл settings.php, который лежит в корне дополнения, я получаю белый экран? Я закомментировал эту строчку и смог войти в панель управления мультисайтом.

Вернул как было.

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

Тут я понимаю что стек трейс я читаю неверно. Что после подключения settings.php файла я оказываюсь выше по стеку:
/wp-admin/network/settings.php(16): current_user_can('manage_network_...')
а урл, который в админке с белым экраном, такой:
.otshelnik-fm.ru/wp-admin/network/
- и тут пришло озарение: что путь подключения, функция require_once, берет не от корня моего дополнения, а от урл моего нахождения /wp-admin/network/settings.php(16) - вот он settings.php и подключается. Только с другого пути. Перечитал описание функций require_once и require и include и башка вскипела.

Константы __DIR__ и __FILE__ выдают мне пути до моего дополнения.

Я переименовал файл в корне моего дополнения на sssettings.php и исправил в 3й строке подключение к нему на новое имя. Белый экран пропал. Я попал в консоль управления мультисайтом.


Решение проблемы:

Решений несколько:

1. Как вариант - не иметь в корне дополнения (или вашего плагина) файла settings.php и вообще таких имен:

2. Или перенести в подпапку inc свой файл settings.php (подозреваю что имя подпапки не должно совпадать с именем подпапки по вышеуказанному пути - не дай боже второй раз совпадение будет)

3. Подключать файл указав полный путь до дополнения:
require_once rcl_addon_path(__FILE__).'settings.php'; - функция wp-recall - содержит полный путь до вашего дополнения на сервере. Можете и ВП аналогичные функции использовать

4. Вводить проверку:

if( is_admin() && !is_network_admin() ){
    require_once 'settings.php';
}

- мы проверяем что мы в админке, но не на странице управления мультисайтом.


Выводы:

Не все очевидно с багами которые нам встречаются. Мультисайтовая сборка доставляет нам еще один опыт. Виновен ли php - или сам мультисайт? У меня прозрение не наступило - сказать не могу. Но мы получили такой опыт.

Гугл не давал мне результатов кроме одного. Теперь стоит запомнить эту ошибку и внимательнее смотреть к репортам пользователей. Возможно одного пользователя я потерял. Но второй меня заставил все таки пошевелиться и отнестись внимательнее к проблеме. Входных данных конечно было мало и это возможно остановило меня при первом репорте.

Дополнения я свои исправлю. Но не буду утверждать что я поддерживаю работу в режиме мультисайта - тестировать еще одну сущность, да крайне редкую не буду. Только по факту обращения с проблемами.

7 комментариев

  1. Ты наверное единственный кто решил потратить свое время и описать эту проблему, я времени на это так и не нашел, хотя тоже ее выявлял. По своему опыту могу добавить, что также крайне не рекомендуется иметь в своем дополнении/плагине файл options.php - будут проблемы.
    Я эти баги связываю с ядром WP, видимо где у него прописаны эти файлы в каких то исключениях и они подключаются не так как все остальные.

    2
    1. В гугле этого почти не было - теперь будет))
      Баг интересный получился - решил покопать. 100% сил конечно решить и выяснить не получилось - но мир чуток светлей стал

      Досада теперь - тратить время и подправлять допы. Я наверно буду исправлять по 4-му методу - воткну проверку

      1
        1. Гугл меня забанил наверно - поэтому я нашел только один комментарий про эту "особенность" (там не один час я поиск и так и эдак на буржуйском юзал. В рунете минут 10 прошелся только - но внятного в индексе не увидел), в тикет системе вордпресса не нашел упоминания. На гитхабе в одном проекте увидел лишь проверку с каментом - что мол если ты в управлении сетью - нефиг подключать тебе settings.php

          Завел себе этот сайт - бывало гуглишь какую-то мелкую неприятность, а найти ее не можешь. Здесь вот и буду свои находки расписывать. Пусть индексируется и пробел заполняется.

          0
  2. Здесь вот и буду свои находки расписывать. Пусть индексируется и пробел заполняется.

    Это большое дело и подспорье однозначно. Полезность огромная именно тонких вещей. Я в читателях постоянных)

    0
    1. Вопрос лишь во времени - писать надо регулярно что-то. Желательно годное, а не очередное - "как добавить кнопки соцсетей на вордпресс сайт". Для этого надо жестко планировать свой распорядок наверно на неделю. Чтобы понимать - седня я пишу на эту тему, завтра я программирую, в среду надо поработать над функционалом да еще учитывать что могут всплывать неожиданные баги и нужно поддерживать обратную связь - все это потребует выделения времени.
      Потом в выходные садиться и планировать вновь.

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

      0

Оставьте комментарий

Авторизация
*
*
Регистрация
*
*
*
Настоящим подтверждаю, что я ознакомлен и согласен с условиями политики конфиденциальности
Генерация пароля
Написать
*
*