PHP遗留项目,最好的方法来获得一个真实的的对象从数据(数据库,请求,文件等)[关闭]

iezvtpos  于 2023-08-02  发布在  PHP
关注(0)|答案(1)|浏览(87)

已关闭。此问题为opinion-based。它目前不接受回答。
**希望改进此问题?**请更新问题,以便editing this post能够以事实和引文来回答。

12天前关闭。
这篇文章是编辑并提交审查6天前.
Improve this question
我有一个关于PHP中真实的对象的问题。
我有一组数据

$userData = [
    'id' => 2,
    'name' => 'Joel',
    'email' => 'joel@gmail.com'
];

字符串
我想用对象示例代替。我想把数组Map到User对象上:

class User
{
    public ?int $id;
    public string $name;
    public string $email;

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }
    
    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }
    
    /**
     * @return string
     */
    public function getEmail(): string
    {
        return $this->email;
    }
    
    /**
     * @param string $email
     */
    public function setEmail(string $email): void
    {
        $this->email = $email;
    }
    
    /**
     * @return int|null
     */
    public function getId(): ?int
    {
        return $this->id;
    }

}


可能的解决方案:将属性添加到构造函数中(以数组形式或逐个添加)。
PHP中有没有其他方法可以达到同样的效果?

stszievb

stszievb1#

你要找的东西叫做Normalizer。它是一个有两个重要方法的类。一个将从对象(normalize)创建数组,第二个将从数组(denormalize)创建对象。
通常这是序列化器的一部分,因为你想以某种格式编码数据,比如JSON。Serializer的最佳工作方式是首先规范化数据(创建一个数组),然后使用Encoder(在本例中是JSON Encoder)对数据进行编码。这是最好的方法,因为你可以把数组编码成任何东西(你可以把它作为数组,你可以把它编码成JSON,XML,...)。
要了解更多信息,您可以查看https://symfony.com/doc/current/components/serializer.html中Symfony Serializer的Serializer组件文档。他们使用特殊的序列化器来进行Doctrine Entities使用属性/注解初始化,所以可能只阅读基本思想而不是实现。
然而,这对于创建一个对象来说是矫枉过正的。最常见的做法是以这种方式创建静态方法fromArray(我相信这是fill函数背后的想法):

class User 
{
    const IMPORTANT_KEYS = ['email', 'name'];

    public static function fromArray(array $data): User
    {
        $keys = array_keys($data);
        foreach (self::IMPORTANT_KEYS as $key) {
            if (!in_array($key, $keys) {
                throw new \InvalidArgumentException('Wrong array given');
            }
        }
        
        $user = new self();
        $user->setName($data['name']);
        $user->setEmail($data['email']);

        return $user;
    }

    ...
}

字符串
这是用旧代码编写的,因为标题中有“legacy”。请记住,如果你将使用PHP 8,你有新的可能性使用,如返回static,这是更好的,如果你的类将在未来扩展。在PHP 8中,你可以这样做:

class User 
{
    public static function fromArray(array $data): static
    {        
        $user = new static();
        $user->setName($data['name'] ?? throw new \InvalidArgumentException('Your array is missing name option.'));
        $user->setEmail($data['email'] ?? throw new \InvalidArgumentException('Your array is missing email option.'));

        return $user;
    }

    ...
}


编辑:你的对象也应该包含setId类,因为你在数组中有id键。如果你正在使用一些对象关系Map系统,比如Doctrine,它会自己生成ID,并且你希望你的应用程序以同样的方式运行,因此如果没有ID的setter,你必须首先创建Reflection类。参见PHP文档
https://www.php.net/manual/en/reflectionclass.newinstance.php

相关问题