2

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

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

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

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

网络服务器 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);
   }
}

?>
4

2 回答 2

5

谁能告诉我是否有解决方案将带有私有成员的 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 等等。

于 2012-12-07T09:43:24.370 回答
1

问题可能是,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,您可能需要自己的辅助方法将对象“转换”为数组。其他可能性是只使用“公共”属性,但这也不是一个好的解决方案。

于 2012-11-30T08:54:03.443 回答