【问题标题】:PHP custom object castingPHP 自定义对象强制转换
【发布时间】:2011-06-23 12:38:14
【问题描述】:

我在 PHP 中有一个名为 product 的自定义类对象:

final class product
{   
    public $id;
    public $Name;
    public $ProductType;
    public $Category;
    public $Description;
    public $ProductCode;
}

当将此类的对象传递给我的数据访问层时,我需要将传递的对象转换为 product 类的类型,以便我可以与该函数中的属性对话。由于 PHP 中的类型转换仅适用于基本类型,因此转换传递的对象的最佳解决方案是什么?

final class productDAL
{
    public function GetItem($id)
    {
        $mySqlConnection = mysql_connect('localhost', 'username', 'password');
        if (!$mySqlConnection) { trigger_error('Cannot connect to MySql Server!'); return; }
        mysql_select_db('databaseName');
        $rs = mysql_query("SELECT * FROM tblproduct WHERE ID='$id';");
        $returnObject = mysql_fetch_object($rs, 'product');
        return $returnObject;
    }

    public function SaveItem($objectToSave, $newProduct = false)
    {
        $productObject = new product();
        $productObject = $objectToSave;

        echo($objectToSave->Name);
        $objectToSave->ID;

    }
}

现在我正在创建一个新对象,该对象转换为 product 类型,然后将其设置为等于传递给函数的对象。有没有更好的方法来完成这项任务?我是不是走错路了?

为清晰而编辑 - 添加完整的 PRODCUTDAL 类

【问题讨论】:

标签: php class types casting


【解决方案1】:

PHP 中的类型转换是这样完成的:

$converted = (type) $from;

请注意,如果对象类型不兼容(例如 $form 恰好是字符串或类型不匹配的对象),这将不起作用。

但通常的解决方案(称为Active Record 模式,例如出现在 Zend 框架中)是为名为 Row 的数据库项创建一个基类。单个项目(例如您的示例中的 product 类)然后从此类继承。

典型的 ZF 场景:

$table = new Product_Table();
$product = $table->find($productId); // load the product with $productId from DB
$product->someProperty = $newPropertyValue;
$product->Save(); // UPDATE the database

IMO 比您的解决方案好得多。

编辑:

你不能在两个不相关的对象之间进行转换,这是不可能的。

如果您想像这样使用 DAL,请跳过“产品”对象并使用简单的关联数组。您可以使用 foreach 枚举其成员,这与对象的属性不同(您可以使用 reflection,但这太过分了)。

我的建议:选择 Active Record 模式(使用magic methods 很容易实现)。它会为您省去很多麻烦。

【讨论】:

  • 我已经尝试过这种方法,但它会产生错误并使页面无用。 ($productObject = (product)$objectToSave;) 我有一个错误捕获系统设置来报告错误,但它甚至不允许页面加载那么远。如果我没记错的话,这种类型的投射只能用特定的对象来完成,对吗? php.net/manual/en/language.types.type-juggling.php
  • $objectToSave 的类型是什么?
  • IMO,类型转换不能用于引用类型变量。因此,即使您将产品转换为一行,它的行为仍然像产品一样,并且仍然具有“对象引用”类型。
  • $objectToSave 的类型是我创建的产品类。另外,我暂时不用ZF。
  • 那么第一个示例中的产品类别与第二个示例中创建的产品类别相同吗?
【解决方案2】:

您不需要投射对象,您可以像使用产品一样使用它。

$name = $objectToSave->Name;

【讨论】:

  • 嗯......你似乎是对的。 NetBeans 中的 Intellisense 无法正常工作,因为它没有正确转换,但似乎这是一个真正的解决方案。以这种方式操作有什么陷阱吗?
  • 哦,欺骗 Intellisense 的好方法:if (false) $objectToSave = new product;。加快开发速度,之后可以删除。
  • 我赞成这个答案。但是有了这个答案,任何 IDE 都不会知道 $objectToSave 是具有 Name 属性的产品。因此,IDE 无法帮助您。用非生产代码欺骗 IDE 以获得有用的智能感知应该是不必要的。真正的转换将使 IDE 知道类型,并提供更好的智能感知/自动完成。
【解决方案3】:

我不确定您要达到什么目的,但如果 $objectToSave 已经属于 product 类:

  • 您可以简单地调用$objectToSave->SaveItem()(假设SaveItem() 是产品类的一部分)并在$this->Name 等函数中访问它的属性;
  • 在您的代码中,$productObject$objectToSave 将包含对同一对象的引用。

【讨论】:

    【解决方案4】:

    目前,您正在创建一个新产品,然后立即丢弃它(因为它的引用已被 $objectToSave 替换。)您需要一个一个地复制它的属性,我很遗憾。

    foreach (get_object_vars($objectToSave) as $key => $value)
    {
        $product->$key = $value;
    }
    

    (如果$objectToSave 的属性是私有的,则需要公开一个调用get_object_vars($this) 的方法to_array()。)

    【讨论】:

    • 如果你想要一个真正的副本,你可以只 clone 对象,但这完全没有必要将它保存在数据库中......
    • clone 不会更改附加到属性的类。
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多