在将对象存储到数据库中并检索它后,我像网站上的许多人一样出现偏移错误。如果我不存储它,一切正常:
$serializedObject = serialize($this);
$unSerializedObject = unserialize($serializedObject);
此外,我在保存数据并从数据库中检索数据时使用base64编码,但这无济于事。不过,我不做任何逃跑。我的对象处理一些字符串。我发现的是,有了这个字符串:
A woman is travelling around the world. She is 28 years old and she is from Great Britain.
She cannot use a car or a plane on her
它工作正常。但是当我再添加一个空格和单词 [ journey] 时,就会弹出错误。这是带有这个单词的字符串:
A woman is travelling around the world. She is 28 years old and she is from Great Britain.
She cannot use a car or a plane on her journey
我的问题是为什么会弹出错误?
这是针对文本运行的serialize($this)
的输出,不带单词 journey
这是针对带有单词 journey
的文本运行的serialize($this)
的输出
更新
我将对象保存到的表中具有字符集utf-8
,并且由于它是 BLOB 类型,因此未定义字符集的列。mb_detect_encoding(serialize($this))
返回UTF-8
$sql
无法逃脱.这就是在我正在使用的 Kohana 框架中执行查询的方式:
$result = mysql_query($sql, $this->_connection)
原答案:
MySQL 中的 TEXT 字段最多存储 65535 个字节,所以我的猜测是它在那里被截断了。
请改用 MEDIUMTEXT 或 LONGTEXT。
除此之外,在将数据传入和传出数据库方面还存在潜在问题。PHP 序列化字符串可以包含空字节(字节 0),这似乎是未正确传输的内容。
解决此问题的一种方法是通过使用非常友好的字母数字/符号字母表的base64_encode()
之类的东西对字符串进行编码。如果您将BLOB
类型增加到 MEDIUMBLOB
或 LONGBLOB
,这将解决您的问题。
但是,如果您正确地将查询发送到数据库,则可以安全地发送原始字符串。由于您使用的是Kohana,因此这里有一个对我来说非常适合的示例。
简短版本:
$sql = 'INSERT INTO serialized_object (data) VALUES (:data)';
DB::query(Database::INSERT, $sql)->
param(':data', $serialization)->
execute();
法典:
<?php
class Article {}
class Word {}
class Controller_Welcome extends Controller
{
public function action_index()
{
$object = unserialize(hex2bin(file_get_contents('/tmp/data.hex')));
$serialization = serialize($object);
$sql = 'INSERT INTO serialized_object (data) VALUES (:data)';
DB::query(Database::INSERT, $sql)->
param(':data', $serialization)->
execute();
$saved_length = DB::query(Database::SELECT, '
SELECT LENGTH(data) AS l
FROM serialized_object
ORDER BY id DESC
LIMIT 1
')->execute()->get('l');
if ($saved_length != strlen($serialization))
{
throw new Exception("Database length is incorrect. Value is corrupted in database.");
}
$saved_serialization = DB::query(Database::SELECT, '
SELECT data
FROM serialized_object
ORDER BY id DESC
LIMIT 1
')->execute()->get('data');
$saved_object = unserialize($saved_serialization);
if (!$saved_object)
{
throw new Exception("Unable to unserialize object.");
}
if ($saved_object != $object)
{
throw new Exception("Saved object is not equal to object.");
}
$this->response->body('Everything is fine.');
}
}
数据库.php:
<?php
return array
(
'default' => array(
'type' => 'PDO',
'connection' => array(
/**
* The following options are available for PDO:
*
* string dsn Data Source Name
* string username database username
* string password database password
* boolean persistent use persistent connections?
*/
'dsn' => 'mysql:host=127.0.0.1;dbname=test',
'username' => 'root',
'password' => '****',
'persistent' => FALSE,
),
/**
* The following extra options are available for PDO:
*
* string identifier set the escaping identifier
*/
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
),
);
图式:
CREATE TABLE `serialized_object` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`data` longblob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
此方法解决了该问题:
$toDatabse = base64_encode(serialize($data)); // Save to database
$fromDatabase = unserialize(base64_decode($data)); //Getting Save Format
但问题仍然存在,Baba
函数findSerializeError
发现错误的根本原因是什么?