【问题标题】:Unserialize() is Not Working, Uncaught Error: Call to a member function on booleanUnserialize() 不工作,未捕获错误:在布尔值上调用成员函数
【发布时间】:2020-07-29 01:16:59
【问题描述】:

我有 3 个类,我将它们序列化并保存到数据库中。其中 2 个很好,我能够毫无问题地检索对象并反序列化它们。有问题的类有 9 个属性。我将一个数组传递给类,同时保存:

  $customer= new Customer($customerValues);
  $serializedCustomer = serialize($customer);
  $auftrag = new Auftrag($auftragValues);
  $serializedAuftrag = serialize($auftrag);

Customer 对象如下所示:

O:5:"Customer"?:{s:9:"*anrede";s:4:"Herr";s:7:"*name";s:11:"ABC";s:8:"*firma";s:11:"test";s:10:"*strasse";s:16:"teststr. 33";s:6:"*plz";s:5:"1234";s:8:"*stadt";s:12:"testcity";s:8:"*mobil";s:12:"0123456789";s:10:"*telefon";s:12:"0123456789";s:8:"*email";s:18:"test@mail.com";}

和 Auftrag 对象:

O:7:"Auftrag":37:{s:14:"*auftrag_typ";s:7:"Angebot";s:9:"*breite";s:3:"2.5";s:8:"*tiefe";s:3:"4.5";s:8:"*hoehe";s:4:"1.00".....

我在两个类中都有以下功能:

public function getProperties() {
      $properties = get_object_vars($this);
      return $properties;
    }

我从数据库中获取数据并反序列化它们:

require_once($_SERVER['DOCUMENT_ROOT'] . '/php/Customer.php');
require_once($_SERVER['DOCUMENT_ROOT'] . '/php/Auftrag.php');

$res = $dbc->fetchAllResults(PDO::FETCH_ASSOC);
$custArr = unserialize($res[0]['customer']);
$auftragArr = unserialize($res[0]['auftrag']);
$customer= $custArr->getProperties();
$auftrag = $auftragArr->getProperties();

当我打印时:print("<pre>".print_r($customer,true)."</pre>"); 我收到一个错误:Fatal error: Uncaught Error: Call to a member function getProperties() on boolean in,但它工作得很好(我得到一个数组),当我打印时:print("<pre>".$auftrag,true)."</pre>"); 当我使用时:print("<pre>".$res[0]['customer'],true)."</pre>"); 我得到了对象,就像上面一样。

这两个对象几乎相同,除了属性。我注意到,有一个“?”在客户"Customer"?:。这可能是个问题吗?或者我在这里做错了什么?

【问题讨论】:

    标签: php oop serialization


    【解决方案1】:

    我通过执行以下操作找到了解决方案:

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

    虽然@atax 的解决方案在指出问题时也是正确的。但是通过使用 base64_encode,它确保了安全地序列化对象。这可以防止数据被破坏,因为 base64 将数据转换为任何排序规则都可以采用的 ASCII。

    【讨论】:

      【解决方案2】:

      根据PHP documentation,如果字符串无效,unserialize 返回false。这就是您的情况 - $custArr 不是 Customer 类的实例,因此会出现错误。

      如果您在反序列化之前添加error_reporting(E_ALL);,您将看到错误消息,因为反序列化会在出现错误时发出通知。序列化的字符串确实有问题。

      我的猜测是对象的值中有一些非 ASCII 符号,由于字符集不匹配,您在保存并从数据库读取后会丢失它们。如果您使用 MySQL,此页面可能会有所帮助 - https://dev.mysql.com/doc/refman/8.0/en/charset.html

      【讨论】:

      • 当我使用 error_reporting(E_ALL); 时得到Notice: unserialize(): Error at offset 14 of 328 bytes in
      • 我删除了表并使用 charset utf-8 再次创建它并创建了一个新类,但错误仍然存​​在。我真的不知道可能是什么原因
      • @tmzafar,PHP 序列化数据对于某些数据库来说不是字符串安全值,因为它包含零字节 (\0)。数据库可能不喜欢它们(顺便说一句,您没有说您使用的是什么数据库)。同样使用 UTF-8 编码重新创建表可能还不够,原因有两个:1)除了 DB 编码,还有客户端编码(您的 db 连接字符串); 2)文本可能包含表情符号,需要4字节编码(MySQL中的utf8mb4)。简单地说,最好的办法是在存储到数据库之前使用base64_encode() 将序列化字符串转换为ASCII 安全的。和base64_decode() 在反序列化之前
      • 更好 - 不要将序列化对象存储在 DB 中,而是以关系 DB 样式存储它们 - 不是 Customer 对象,而是 customer_id,它是对另一个表的引用。
      猜你喜欢
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 2015-11-04
      • 1970-01-01
      相关资源
      最近更新 更多