【问题标题】:Error saving object with private member to MongoDb with PHP Driver使用 PHP 驱动程序将具有私有成员的对象保存到 MongoDb 时出错
【发布时间】:2012-11-30 04:05:09
【问题描述】:

谁能告诉我是否有解决方案将带有私有成员的 PHP 类保存到 MongoDb?我不断收到以下错误

zero-length keys are not allowed, did you use $ with double quotes?'

我看到至少有两个与同一个问题有关的现有问题,但没有真正的答案。
Question 1 Question 2

我所有的持久性类都有一个我需要可用的私有成员,但我不想创建一个函数来避免私有成员的必要性,因为这是一个基于实例的类,它具有利用私有成员的多个功能。

Web 服务器 Apache/2.2.22

PHP 版本 PHP 5.4.6

PHP 扩展 mongo/1.2.6

这将是一个示例实现,请不要批评代码本身,它只是为了说明行为的类型,即 $this 的 Save 和基本类型中的 $private 成员:

<?php

class PersistableObject extends AbstractBasePersistableObject
{
   public  $PublicSubTypeProperty;

    public function __construct()
    {
       parent::__construct();
    }

    public function GetDalConfigurationFromSubType()
    {
        //This object is just a wrapper DAL implemented based on
        //the php Mongo, MongoDb and MongoCollection objects
        return new MongoBasedDal();
    }
}


abstract class AbstractBasePersistableObject
{
   private $dalRef = null;
   public $PublicBaseProperty;

   public abstract function GetDalConfigurationFromSubType();

   public function __construct()
   {
      $this->dalRef = $this->GetDalConfigurationFromSubType();
   }

   public function Save()
   {
       $this->dalRef->Save($this);
   }
}

?>

【问题讨论】:

  • 你是在课堂上存钱吗?或者只是保存类对象?您可以发布保存代码吗?
  • @daveh,我已经在原始问题中发布了编码
  • 我已经升级到Mongodb 2.2.2,问题依旧。

标签: php mongodb


【解决方案1】:

谁能告诉我是否有解决方案将带有私有成员的 PHP 类保存到 MongoDb?

正如您从 Google Groups 中了解到的那样,问题在于 PHP 驱动程序实际上在保存时忽略了私有变量和受保护变量。这是驱动程序本身核心中的一个基本问题,因此没有简单的解决方法。你也知道 Derick 为此创建了一个 JIRA:https://jira.mongodb.org/browse/PHP-624

@harald 实际上确实说明了方法,创建您自己的 _to_array() 并将其提供给 save 函数,不幸的是,这再次导致您如何构建类的基本问题。您必须像这样使用反射:

$reflect = new ReflectionClass(get_class($this));
$class_vars = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE);

foreach ($class_vars as $prop) {
    $doc[$prop->getName()] = $this->{$prop->getName()};
}

然后在存档中使用$doc

但是,您可以通过创建一个预定义的 $schema 数组来稍微更改您的编程以避免反射(或者只是缓存反射的结果以节省资源消耗),该数组将包含您希望的所有字段节省。当您希望按需添加新字段时,您可以让您的 __set__get 更新内存模式数组。这样你就可以完全避免反射,只去抓取模式数组和它的值。

这是许多框架用来解决问题的方法,包括 Lithium、Yii、Kohona、CakePHP 等等。

【讨论】:

    【解决方案2】:

    问题可能是,Mongo 正在尝试将您的对象转换为数组。如果您正在查看...的输出...

    class Address{
        private $name;
        private $company;
        private $zip;
    
        public function __construct($name,$company,$zip){
            $this->name = $name;
            $this->company = $company;
            $this->zip = $zip;
        }
    }
    
    print_r((array)new Address('name', 'company', 'zip'));
    

    ... 使用 hexdump,它将显示以下内容:

    harald:$ ~/test.php | hexdump -C
    00000000  41 72 72 61 79 0a 28 0a  20 20 20 20 5b 00 41 64  |Array.(.    [.Ad|
    00000010  64 72 65 73 73 00 6e 61  6d 65 5d 20 3d 3e 20 6e  |dress.name] => n|
    00000020  61 6d 65 0a 20 20 20 20  5b 00 41 64 64 72 65 73  |ame.    [.Addres|
    00000030  73 00 63 6f 6d 70 61 6e  79 5d 20 3d 3e 20 63 6f  |s.company] => co|
    00000040  6d 70 61 6e 79 0a 20 20  20 20 5b 00 41 64 64 72  |mpany.    [.Addr|
    00000050  65 73 73 00 7a 69 70 5d  20 3d 3e 20 7a 69 70 0a  |ess.zip] => zip.|
    00000060  29 0a                                             |).|
    00000062
    

    看看 .Address.name 中的那些点,它们是空字节,可能不允许在键中使用,因此会导致奇怪的错误消息。

    由于 PHP(还)没有魔术方法 __to_array,您可能需要自己的辅助方法将对象“转换”为数组。其他可能性是只使用“公共”属性,但这也不是一个好的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      • 1970-01-01
      • 2013-12-13
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-23
      相关资源
      最近更新 更多