【问题标题】:PDO fetch into existing objectPDO 提取到现有对象
【发布时间】:2013-12-29 07:43:56
【问题描述】:

我正在尝试使用 PDO 将数据从数据库中提取到当前对象中。代码:

class Voucher {

    //Database and object have EXACTLY the same fields/properties/columns

    protected $voucher_id;
    protected $voucher_code;
    protected $voucher_value;
    protected $voucher_product_type;
    protected $voucher_status;

    // still in the class declaration
    public function load_voucher($voucher_code){

        global $conn;  //load database connection info

            $stmt = $conn->prepare('select * from cart_voucher_table where voucher_code = :voucher_code');
            $stmt->execute(array('transaction_id' => $this_transaction_id));

             I HAVE NO IDEA, NO PDO statement works

            // Current object (which existed but was empty) now contains values from first row of returned data from db
     }
}

//用法

$this_voucher = new voucher();   //creates new voucher object
$this_voucher->load_voucher($voucher_code);  //loads data from database into the current voucher object.

我找了好久,没有结果。我见过的所有解决方案要么具有类之外的函数,要么返回一个新对象,而不是当前对象。

【问题讨论】:

  • 当您为voucher_code 准备语句时执行时,您正在映射transaction_id。此外,$this_transaction_id 未定义,但我确定您的意思是使用 $this->transaction_id
  • 你遇到了什么错误?
  • 是的。解决了这个问题。它仍然不起作用。它在 $stmt->setFetchMode(PDO:FETCH_CLASS, 'Voucher'); 上失败这是在实际执行查询之前。错误是:未捕获的异常 'PDOException' 带有消息 'SQLSTATE[HY093]:无效的参数号:未定义参数
  • 我已经尝试了设置获取模式和执行我能想到的语句的所有变体。我相信我需要一行来设置 PDO 模式以获取当前对象,但我不知道如何设置它。
  • 在执行前尝试使用bindValue()

标签: php pdo


【解决方案1】:

在模型/值对象中使用 PDO 来填充对象的属性是一个糟糕的设计决策。我不是说要敲你的代码,而是鼓励你使用不同的技术。仅在可维护性方面避免的痛苦就值得选择新设计的努力。解决后我有一个建议。

解决方案

此问题之前已在此处处理过:“PDO's FETCH_INTO $this class does not working”。使用该技术应该可以解决您的问题。

建议

我的建议是完全走另一条路。考虑创建一个看起来像这样的 Voucher DAO:

class VoucherDao
{
    private $db;

    public function __construct(\PDO $db)
    {
        $this->db = $db;
    }

    public function findVoucher($voucher_code)
    {
        $stmt = $this->db->prepare('select * from cart_voucher_table where voucher_code = :voucher_code');
        $stmt->bindValue(':voucher_code', $voucher_code);
        $stmt->setFetchMode(\PDO::FETCH_CLASS, 'Voucher');
        $stmt->execute();

        return $stmt->fetch();
    }
}

您可以使用 DAO 创建已填充数据的凭证,而不是创建新凭证然后加载它。

$dao = new VoucherDao($conn);
$voucher = $dao->findVoucher(12345);

当然,由于我没有完整的优惠券代码,我无法对此进行测试。如果我没记错的话,您需要在您的 Voucher 类中创建设置器以允许 PDO::FETCH_CLASS 正常工作。如果您尝试我的建议,请尝试使用和不使用。

【讨论】:

  • 谢谢。你的回答解决了这个问题。我也很欣赏我做错了的建议。我将创建一个单独的类,就像您在上面显示的那样。一般来说,这是一个好的设计决策吗?我应该创建一个包含对象的类,然后创建其他类来做其他事情,还是这特定于通过 PDO 加载数据?
  • 是的,您应该创建专注于事情的类。这种职责分离风格是单一职责原则 (en.wikipedia.org/wiki/Single_responsibility_principle) 的应用,它是 SOLID 原则 (en.wikipedia.org/wiki/SOLID_(object-oriented_design)) 的一部分。你会感谢自己在路上付出的额外努力。
  • VoucherService 应命名为 VoucherDao,因为它负责数据访问(在我查找、保存、更新等的 Dao 类中)。
【解决方案2】:

“input_parameters 中的键必须与 SQL 中声明的键相匹配。在 PHP 5.2.0 之前,这被忽略了。”

发件人:http://www.php.net/manual/de/pdostatement.execute.php

在您的 MySQL 中,在准备语句时,您有命名参数“:voucher_code”,但要执行的数组中的键是“transaction_id” - 所以我猜这可能是您的问题,因为您写了关于获取的评论有关参数的错误消息。

另外,我没有看到 $stmt->fetch() 在您的代码中的任何地方被调用...?

【讨论】:

  • 我修复了参数名称的问题。我什至没有到达 fetch()。我只是想将 fetch 设置为 fetch 到当前对象中。 $stmt->setFetchMode(PDO::FETCH_CLASS, new Voucher);给出:致命错误:未捕获的异常 'PDOException' 带有消息 'SQLSTATE[HY000]:一般错误:类名必须是字符串。 $stmt->setFetchMode(PDO::FETCH_CLASS, "凭证");给出:致命错误:未捕获的异常 'PDOException' 带有消息 'SQLSTATE[HY093]:无效的参数号:未定义参数
猜你喜欢
  • 2011-11-09
  • 2014-10-28
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多