Вопрос или проблема
Я использую транзиент таким образом (простой пример):
function my_url_cache( $url )
{
$transient_id = hash( "crc32", $url );
$content = get_transient( 'my_url_cache_' . $transient_id );
set_transient( 'my_url_cache_' . $transient_id, $content, 60 * 60 * 24 );
set_transient( 'my_url_cache_backup_' . $transient_id, $content, 0 );
}
Вместе с плагином моей компании у них возникает эта ошибка, когда они хотят обновить свой кэш:
Вызов метода get() для не объекта в
/wordpress/wp-includes/cache.php на строке 123
Без моего плагина у них нет проблем
/wordpress/wp-includes/cache.php на строке 123:
/**
* Извлекает содержимое кэша по ключу и группе.
*
* @since 2.0.0
*
* @see WP_Object_Cache::get()
* @global WP_Object_Cache $wp_object_cache Глобальный экземпляр кэша объектов.
*
* @param int|string $key Ключ, под которым хранится содержимое кэша.
* @param string $group Необязательно. Где содержимое кэша сгруппировано. По умолчанию пусто.
* @param bool $force Необязательно. Обновлять ли локальный кэш из постоянного кэша.
* По умолчанию false.
* @param bool $found Необязательно. Найден ли ключ в кэше. Различает возвращаемое значение false,
* хранимое значение. Передается по ссылке. По умолчанию null.
* @return bool|mixed False в случае неудачи получения содержимого или содержимое кэша
* в случае успеха
*/
function wp_cache_get( $key, $group = '', $force = false, &$found = null ) {
global $wp_object_cache;
return $wp_object_cache->get( $key, $group, $force, $found ); // Строка 123
}
На моем тестовом сервере я не могу воспроизвести эту ошибку.
Они не используют другую систему кэширования.
Похоже, что $wp_object_cache не является объектом. Я не знаю, связано ли это с моим плагином, их плагином или обоими.
Должен ли я использовать специальный хуки в WordPress, прежде чем я смогу использовать функции get_ и set_transient? Я использую свою функцию кэширования только внутри этого хуки:
add_shortcode( 'feedimport', array( $this, "shortcode_feedimport" ) );
ОБНОВЛЕНИЕ:
Другой плагин использует wp_schedule_event:
private static function cron_schedule_event_setup() {
wp_clear_scheduled_hook(self::cron_hook);
wp_schedule_event(time(), self::$options['schedule_event'], self::cron_hook);
}
И сохраняют свои данные в таблице базы данных. Они не используют функции get_ set_transient. 🙁
Я действительно не знаю, как мой плагин может повлиять на их плагин. Полный код их плагина: ссылка
Обновление 2 – Решено:
public function __destruct() {
$this->save_log();
}
Этот код запускает функцию, которая использует систему кэширования WordPress.
Изменив на это:
add_action('shutdown', array($this, "save_log"));
Проблема была решена. Я больше никогда не использую функции WordPress в деструкторе.
Действительно, вы должны быть осторожны при использовании __destruct
.
Это специальная функция, которая срабатывает, когда объект собирается быть уничтожен. Когда PHP вызывает exit
(как делает wp_send_json()
), мы не контролируем, в каком порядке PHP будет уничтожать объекты.
Таким образом, __destruct
очень опасен, когда он зависит от других классов. Я видел, как это вызывает фатальные ошибки, особенно в PHP 5.6, что приводит к ошибкам, таким как:
/**
* Деструктор задания
*/
public function __destruct()
{
$this->logger->commit();
}
Фатальная ошибка: Нервный сбой: Вызов метода commit() для null
Решение
Вместо:
$job = new Job;
wp_send_json($job->start());
Делайте:
wp_send_json((new Job)->start());
Что аналогично:
$job = new Job;
$results = $job->start();
// Запустите __destruct, пока мы находимся в известном состоянии
unset($job);
wp_send_json($results);
Вы должны сделать это, когда процесс PHP будет прерван с помощью exit
или die
.
wp_send_json()
является наиболее заметным примером, поскольку мы используем его часто и он вызывает exit
сразу после вывода строки JSON. Но это также может применяться к другим функциям, таким как wp_die()
, exit
, die
и т.д.
В конечном счете, просто убедитесь, что функция, которая использует __destruct
, уничтожается, если процесс PHP будет прерван, иначе это может вызвать проблемы.
Доказательство концепции: https://3v4l.org/GBBIV
Ответ или решение
Ошибка PHP Fatal Error: $wp_object_cache is non-object
Ошибка, которую вы наблюдаете, указывает на то, что переменная $wp_object_cache
не является объектом в момент ее вызова в функции wp_cache_get
. Ваша проблема возникла на сервере клиента при использовании вашего плагина, в то время как тестовый сервер не проявил аналогичных проблем. Давайте подробно рассмотрим возможные причины и решения этой ошибки.
1. Понимание проблемы
При вызове функции wp_cache_get
(где возникает ошибка на строке 123 в файле cache.php
) происходит попытка доступа к методу get()
объекта $wp_object_cache
. Если переменная не инициализирована или не содержит корректный объект, система выдаст ошибку «Fatal Error».
2. Что может вызвать данную ошибку
-
Неинициализированная переменная: На вашем тестовом сервере объект кэша мог быть инициализирован, тогда как на клиентском сервере этого не произошло. Обычно
$wp_object_cache
инициализируется при загрузке ядра WordPress, и если ваш плагин мешает этому процессу (например, в__destruct
методе или при неправильных вызовах), это может привести к проблемам. -
Использование функции в неправильный момент: Ваша функция кэширования должна вызываться в правильный момент жизненного цикла WordPress. Если вы вызываете
get_transient
илиset_transient
слишком рано (например, до полной инициализации WordPress), это может вызвать ошибки.
3. Как решить проблему
Судя по вашему обновлению, ошибка была вызвана использованием функций WordPress в методе __destruct
. Это является плохой практикой, поскольку функции WordPress могут быть заблокированы или не доступны в момент уничтожения объекта. Вместо этого рекомендуем использовать add_action
с хуком shutdown
, чтобы убедиться, что ваши функции вызываются в правильное время.
Изменение вашего кода:
Вместо:
public function __destruct() {
$this->save_log();
}
Используйте:
add_action('shutdown', array($this, "save_log"));
Это гарантирует, что функция будет выполнена на этапе завершения выполнения всех действий, при этом не нарушая жизненный цикл объектов.
4. Рекомендации по разработке
-
Избегайте
__destruct
для функций WordPress: Используйте хуки и действия WordPress для выполнения кода, связанным с состоянием или событиями в WordPress. -
Логирование ошибок: Включите логирование ошибок в
wp-config.php
для более детального анализа возможных причин.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
- Проверяйте наличие объекта: Перед использованием методов объекта, всегда проверяйте, является ли он инициализированным. Например:
if (is_object($wp_object_cache)) {
$wp_object_cache->get($key, $group, $force, $found);
} else {
error_log('WP_Object_Cache is not initialized.');
}
Заключение
Сложности, подобные вашей, могут возникать в процессе разработки плагинов и тем для WordPress. Важно следить за тем, чтобы архитектура кода соблюдала жизненный цикл WordPress, использовать хуки должным образом и избегать нестандартных подходов, таких как использование метода __destruct
. Применение предложенных мер поможет устранить возникшую ошибку и улучшить стабильность вашего плагина.