【问题标题】:Is there any way to convert an array to class properties?有没有办法将数组转换为类属性?
【发布时间】:2015-08-01 21:40:43
【问题描述】:

有一种方法可以获取类属性并使用(array) 转换进行转换。

$user = (array) get_object_vars($userObject)

但我想知道,我没有找到任何将数组转换为类属性的直接方法。

假设我有以下实现的用户类:

class User
{
    private $id = 0;
    private $fname = '';
    private $lname = '';
    private $username = '';
}

我有以下数组:

$user = array(
    'id'=> 2,
    'fname' => 'FirstName',
    'lname' => 'LastName',
    'username' => 'UserName'
);

我正在寻找一种类型转换,就像我们有 (object) 一样。问题是(object) 类型转换将数组转换为stdClass 对象,但在这里我希望将我的数组转换为我指定的类。

示例应该这样表述:(我的假设,PHP 应该有这个。或者它可能已经有类似的东西,我不知道。)

$userobj = (object User) $user;

以上语法的结果应该是这样的:

$userobj->id = $user['id'];
$userobj->fname = $user['fname'];
$userobj->lname = $user['lname'];
$userobj->username = $user['username'];

我想知道有没有直接的方法,不是映射的逻辑。寻找语言级别的技巧。

注意:我知道使用foreach 来完成上述工作。我正在寻找一些直接的方法,如果在 PHP 中可用,但还没有成为焦点(可能是!)。

以下并不能解决我的问题: Convert/cast an stdClass object to another class

【问题讨论】:

  • 您必须编写自己的自定义方法才能做到这一点。原因是对象不知道如何处理不同的属性或尚未定义的属性。类似 $object->load($array).
  • 如果您从数据库中获取,大多数 API 都有 fetch_object() 或类似名称,您可以在其中指定类。
  • 那么直接回答你的问题是:不,PHP中不存在这种东西。

标签: php arrays class object type-conversion


【解决方案1】:

数组不是对象。所以你不能用语言结构来投射它。即使在 PHP 中强制转换用户定义的对象也是不可能的。

所以你必须编写自己的逻辑。 serialize() 对象有一些奇特的方法,更改类名并再次unserialize() 以自动化该过程。

您还可以使用反射编写强制转换函数。但一切都需要用户逻辑。

另请参阅 SO 上的此帖子:Type casting for user defined objects

所以如果你真的喜欢投射对象,我最终会使用这个函数 (see it in action):

function cast($to, $obj)
{
    $toLength = strlen($to);
    $serializedObj = preg_replace('/^O:\\d+:"[^"]+"/', 'O:' . $toLength . ':"' . $to . '"', serialize($obj));

    $serializedObj = preg_replace_callback('/s:(\\d+):"([^"]+)";(.+?);/', function($m) use($to, $toLength) {
        $propertyName = $m[2];
        $propertyLength = $m[1];

        if(strpos($m[2], "\0*\0") === false && ($pos = strrpos($m[2], "\0")) !== false) {
            $propertyName = "\0" . $to . "\0" . substr($m[2], $pos + 1);
            $propertyLength = ($m[1] + $toLength - $pos + 1);
        }

        return 's:' . $propertyLength . ':"' . $propertyName . '";' . $m[3] . ';';
    }, $serializedObj);

    return unserialize($serializedObj);
}

$user = array(
    'id'=> 2,
    'fname' => 'FirstName',
    'lname' => 'LastName',
    'username' => 'UserName'
);

$userObj = cast(User::class, (object)$user);

print_r($userObj);

但我永远不会在生产中使用此功能。这只是一个实验性的东西。

更新

好的,我重新考虑了 Java 中如何处理强制转换。在 Java 中,您实际上可以从一个对象强制转换为它的子对象。您不能从任何对象投射到任何其他对象。

所以你可以在 Java 中做到这一点:

$apple = new Apple();
$macintoshApple = (MacintoshApple)$apple;

鉴于MacintoshApple extends Apple

但是你不能投射两个不相关的对象,比如:

$apple = new Apple();
$pear = (Pear)$apple;

【讨论】:

  • 非常好的功能,但这里还有一个问题是你的答案;与foreach逻辑的性能对比如何?
  • 我只能猜测,但根据我的经验,我会说序列化和反射方法在性能上都不能胜过 foreach。
  • 你是对的,我只是比较了两者,发现foreach方法的速度几乎翻了一番。
【解决方案2】:

根据您对@AbraCadaver 评论的回复,我会考虑使用类似的方法将数据库结果加载到您选择的实例化类中:

// using MySQLi
$mysqli_result = ...; // your mysqli_result object
while($class_obj = $mysqli_result->fetch_object('your_class_name')) {
    // do something
}

// using PDO
$pdo_statement = ...; // your PDOStatement object
while($class_obj = $pdo_statement->fetch_object('your_class_name')) {
    // do something
}

【讨论】:

  • 你好,迈克,我的评论是得到类似fetch_object 的东西,但我没有使用/从数据库中获取数据。我的例子很好地解释了它。 :)
猜你喜欢
  • 1970-01-01
  • 2020-08-03
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 1970-01-01
  • 2023-01-05
  • 2018-09-11
相关资源
最近更新 更多