【问题标题】:Dynamically create PHP object based on string基于字符串动态创建 PHP 对象
【发布时间】:2011-01-13 04:00:16
【问题描述】:

我想根据 MySQL 数据库中的字符串定义的类型在 PHP 中创建一个对象。数据库表有以下列和样本数据:

 id | type | propertyVal
----+------+-------------
  1 | foo  | lorum
  2 | bar  | ipsum

...使用 PHP 数据类型

class ParentClass {...}
class Foo extends ParentClass {private $id, $propertyVal; ...}
class Bar extends ParentClass {private $id, $propertyVal; ...} 
//...(more classes)...

仅使用一个查询,我想通过 id 选择一行并创建一个类型定义表的类型列的对象,并将 SELECTed 行中的其他列分配给新创建的对象。

我在想使用:

  1. mysql_fetch_object()
  2. 读取类型属性
  3. 使用由 type 属性定义的类型创建对象

但不知道如何根据字符串动态创建类型。如何做到这一点?

【问题讨论】:

    标签: php mysql oop casting


    【解决方案1】:

    但不知道如何根据字符串动态创建类型。如何做到这一点?

    您可以轻松自然地做到这一点:

    $type = 'myclass';
    
    $instance = new $type;
    

    如果您的查询返回一个关联数组,您可以使用类似的语法分配属性:

    // build object
    $type = $row['type'];
    $instance = new $type;
    
    // remove 'type' so we don't set $instance->type = 'foo' or 'bar'
    unset($row['type']);  
    
    // assign properties
    foreach ($row as $property => $value) {
       $instance->$property = $value;
    }
    

    【讨论】:

    • 你也可以将参数传递给构造函数 $instance = new $type(5, 'hi');
    • 注意className必须是全路径、有效的class地址,例如:` $type = "app\models\MyClass"; `
    【解决方案2】:

    有一种非常简洁的语法可以使用,我在几个月前了解到,它不依赖于临时变量。这是我使用 POST 变量加载特定类的示例:

    $eb = new ${!${''} = $_POST['entity'] . 'Binding'}();
    

    不过,在您的具体情况下,您可以使用 PDO 来解决它。它有一个获取模式,允许第一列的值是该行实例化到的类。

    $sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
    

    【讨论】:

    • 我不明白,显然你会收到$eb= new ${FALSE}(); 还是我错过了什么??
    • 这个 hack 起作用的原因是因为${false} 的计算结果为${''}(与写(string)false 相同)并且名称为[empty string] 的变量是我们刚刚在内部创建的变量括号子句。非常漂亮。
    • 这个语法叫什么名字?我在哪里可以阅读更多关于它的信息?因为我不明白。
    【解决方案3】:
    $instance = new $classname; // i.e. $type in your case
    

    效果很好……

    【讨论】:

    • 那么如何添加构造函数的参数呢?这样做是否有效: $instance = new $classname($parameterA, $parameterB);
    【解决方案4】:

    以下是我来到这个帖子时正在寻找的内容。使用{"objectName"}(括号)以字符串的形式声明或引用对象名。

    $gameData = new stdClass();
    $gameData->location = new stdClass();
    $basementstring = "basement";
    
    class tLocation {
        public $description;
    }
    
    $gameData->location->{'darkHouse'} = new tLocation;
    $gameData->location->{"darkHouse"}->description = "You walkinto a dusty old house";
    
    
    $gameData->location->{$basementstring} = new tLocation;
    $gameData->location->{"basement"}->description = "its really damp down here.";
    
    //var_dump($gameData); 
    echo $gameData->location->basement->description;
    

    这种引用对象的方式似乎可以互换。我找不到答案,所以我只好胡闹直到找到方法。

    【讨论】:

      【解决方案5】:

      正如 Silkfire 所说,这可以通过使用 PDO 特定模式来实现,所以这里是一个示例。使用相同的数据库值和定义的对象:

      编号 |类型 |财产价值 --+--------+------------- 1 |富 |劳伦 2 |酒吧 | ipsum 类父类 {...} Foo 类扩展 ParentClass {private $id, $propertyVal; ...} 类 Bar 扩展 ParentClass {private $id, $propertyVal; ...} //...(更多课程)...

      使用单个查询(您必须首先命名包含类名的字段):

      $stmt = $db->prepare('SELECT type,id,propertyVal FROM table WHERE id=1');
      $stmt->execute();
      $foo = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
      var_dump($foo); // $foo is a newly created object of class foo, with properties named like and containing the value of subsequent fields
      

      这很酷,但一段时间后会变凉

      $stmt = $db->prepare('SELECT type,id,propertyVal FROM table');
      $stmt->execute();
      while ($object = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE))
       {var_dump($object);} // here all desired objects, dynamically constructed accordingly to the first column returned by the query
      

      您可以定义一个构造函数(将在将数据库中的值分配给属性后调用该构造函数)来处理这些动态分配的属性,例如用大写值替换字符串

      class foo
       {function __construct ()
         {$this->uper = strtoupper($this->propertyVal);}}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-20
        • 1970-01-01
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多