5

在将对象存储到数据库中并检索它之后,我在网站上遇到了许多偏移错误。如果我不存储它一切正常:

$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

它工作正常。但是当我再添加一个空格和单词[旅程]时,就会弹出错误。这是带有这个单词的字符串:

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

serialize($this)是针对带有单词的文本运行的输出journey

更新

我将对象保存到的表具有字符集utf-8和未定义字符集的列,因为它是 BLOB 类型。mb_detect_encoding(serialize($this))回报_UTF-8

没有逃脱的$sql。这就是我正在使用的 Kohana 框架中执行查询的方式:

$result = mysql_query($sql, $this->_connection)
4

2 回答 2

8

原答案:

MySQL 中的 TEXT 字段最多存储 65535 个字节,所以我猜它在那里被截断。

请改用 MEDIUMTEXT 或 LONGTEXT。

除此之外,如何将数据输入和输出数据库还存在潜在问题。PHP 序列化字符串可以包含空字节(字节 0),这似乎是没有正确传输的内容。

base64_encode()解决此问题的一种方法是通过使用非常友好的字母数字/符号字母表的方式对字符串进行编码。如果您将BLOB类型增加到MEDIUMBLOBor ,那将解决您的问题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
于 2013-10-19T18:05:46.557 回答
3

用这种方法解决了这个问题:

$toDatabse = base64_encode(serialize($data));  // Save to database
$fromDatabase = unserialize(base64_decode($data)); //Getting Save Format 

Baba但问题仍然存在, 's functionfindSerializeError发现错误的根本原因是什么?

于 2013-10-19T18:10:18.847 回答