PHP unserialize: проблема с длиной строковых переменных
В ходе перевода одного старого проекта на фреймворк Kohana столкнулся с проблемой конвертации сериализованных переменных. Работа программы прерывалась вылетом следующего Exception:
[ Notice ]: unserialize(): Error at offset 192 of 45949 bytes
После детального разбирательства было выяснено, что процесс конвертации прерывается на восстановлении строковых переменных, причем, только тех, которые содержали символы кириллицы. Объяснение этому нашлось быстро: в старом проекте используется кодировка KOI8, Kohana, естественно, использует UTF-8, а PHP при сериализации указывает длину строки в байтах, а не символах.
Если serialize()
используется для хранения php-переменных в базе данных, то достаточно просто перекодировать данные в БД. Для этого, сначала данные, прочитанные из БД, необходимо восстановить в родной кодировке. Затем перекодировать в новую кодировку, сериализовать и сохранить в базе данных.
Метод, описанный выше, не подходит, если требуется одновременная работа старой и новой версии проекта или сериализованное значение переменной получено от другого приложения, например по протоколу RPC. В этом случае для решения проблемы нужно сначала пересчитать длину всех строковых переменных в хранимом представлении, а затем вызвать функцию десериализации.
Можно использовать готовую функцию, а для фреймворка Kohana написать расширение системного класса UTF8. Создайте файл с таким содержимым
<?php defined('SYSPATH') or die('No direct script access.');
class UTF8 extends Kohana_UTF8
{
/**
* @param string строка для unserialize
* @return mixed
*/
public static function unserialize($string)
{
$str = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $string);
return unserialize($str);
}
}
сохраните его с именем utf8.php в каталоге application/classes.
Для восстановления PHP-значения используйте следующий вызов
UTF8::unserialize($serial_str)