maybe_serialize() – функция сериализует значение, если оно нуждается в этом

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

В рамках WordPress сериализация используется такими функциями, как update_option() или update_site_meta() для того, чтобы было возможно сохранять структурные данные настроек сайта в базу данных, где всё хранится в скалярных значениях.

Функция сериализует только массивы и объекты (первоначально так и задумывалось). Но со строками в итоге возник некоторый моментик – те строки, которые сериализованы, будут сериализованы повторно, а обычные строки – никак не будут обработаны. Об этом подробнее тут.

maybe_serialize( $data )

Параметры

$data
(строка|массив|объект) Данные, которые (возможно) нужно сериализовать.

Повторая сериализация строк

Это может показаться нелогичным, но оно оставлено для (да, угадали) поддержки обратной совместимости.

Дело в том, что когда эта функция появилась много-много лет назад, то она так и работала, как работает сейчас – производила повторные сериализации строк. А ещё обратная функция maybe_unserialize(), которая являлась частью функций для получения опций из базы данных, например я говорю о get_option(), всегда производила десериализацию только сериализованных значений.

И пока это так работало, разные разработчики начали неправильно использовать API опций WordPress, например они делали:

update_option( 'my_plugin_options', serialize( array( 'привет', 'мир', '!' ) ) );
unserialize( get_option( 'my_update_plugins' ) );

Вместо того, чтобы делать правильно:

update_option( 'my_plugin_options', array( 'Привет', 'мир', '!' ) );
get_option( 'my_update_plugins' ); // и так возвращает массив

Суть в том, что когда решили обновить функцию maybe_serialize() и исключить из неё возможность повторной сериализации, то плагины тех неумелых разработчиков перестали работать! Потому что в базе данных у нас сериализованная один раз строка, а потом, когда мы получаем её функцией get_option(), она автоматически десериализуется один раз, а потом ещё и разработчик запихивает уже готовое значение в PHP-функцию unserialiaze() и в итоге получаем PHP-уведомление + ничего не работает Warning: unserialize() expects parameter 1 to be string, array given.

В итоге пришлось оставить эту повторную сериализацию для поддержки этих кривых плагинов, к сожалению.

Поэтому, на сегодняшний день, если вы хотите предотвратить эту повторную сериализацию данных, то вам придётся использовать условие с функцией is_serialized().

if( ! is_serialized( $data ) ) {
	$data = maybe_serialize( $data );
}

Примеры

// Обычные несериализованные строки функция никак не обрабатывает
echo maybe_serialize( 'Привет мир!' ); // Привет мир!
 
// Другие скалярные данные, числа, логические, null, также никак обработаны не будут
echo maybe_serialize( 21 ); // 21
var_dump( maybe_serialize( false ) ); // false
 
// Массив будет преобразован в сериализованную строку
echo maybe_serialize( array( 'text' => 'Привет, мир!', 'image' => 'mountain.jpg' ) );
// a:2:{s:4:"text";s:21:"Привет, мир!";s:5:"image";s:12:"mountain.jpg";}
 
// Сериализованная строка будет сериализована повторно 🙁
echo maybe_serialize( 'a:2:{s:4:"text";s:21:"Привет, мир!";s:5:"image";s:12:"mountain.jpg";}' );
// s:78:"a:2:{s:4:"text";s:21:"Привет, мир!";s:5:"image";s:12:"mountain.jpg";}";

Источник: Блог Миши Рудрастых

Миша Рудрастых

Путешествует по миру и рассказывает всем о WordPress лично, у себя в блогах и на курсах в Санкт-Петербурге. Умеет просто объяснять сложные вещи, делает это красиво. Организовывает неплохие WordCamp's, но совсем не умеет слушать чужие доклады.

Добавить комментарий

%d такие блоггеры, как: