Php PDO获取到现有对象

Php PDO获取到现有对象,php,pdo,Php,Pdo,我试图使用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; prote

我试图使用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.
我找了很长时间,没有结果。我看到的所有解决方案要么在类外具有函数,要么返回新对象,而不是当前对象。

“输入参数中的键必须与SQL中声明的键匹配。在PHP 5.2.0之前,这被默默忽略。”

发件人:

在您的MySQL中,在准备语句时,您有一个命名参数“:concedure_code”,但要执行的数组中的键是“transaction_id”-因此,我想这可能是您的问题,因为您在获取有关参数的错误消息时写了一条注释


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

在模型/值对象内部使用PDO填充对象的属性是一个糟糕的设计决策。我这么说不是为了敲打你的代码,而是为了鼓励你使用不同的技术。仅在可维护性方面避免的痛苦将值得您为选择新设计而付出努力。解决问题后我有一个建议

解决方案

此问题以前在此处讨论过:“”。使用这种技巧可以解决您的问题

建议

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

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);

当然,因为我没有完整的凭证代码,所以我无法测试它。如果我没记错的话,您需要在凭证类中创建setter,以允许
PDO::FETCH_类
正常工作。如果您尝试一下我的建议,请使用和不使用进行测试。

当您为
凭证\u代码
准备对账单时执行时,您正在映射
交易\u id
。另外,
$this\u transaction\u id
没有定义,尽管我确信您的意思是使用
$this->transaction\u id
您得到了什么错误?是的。修正了。它仍然不起作用。它在$stmt->setFetchMode(PDO:FETCH_类,“凭证”)上失败;这是在实际执行查询之前。错误是:未捕获异常“PDOException”,消息为“SQLSTATE[HY093]:参数编号无效:未定义参数我尝试了设置fetch模式和执行我能想到的语句的各种方法。我相信我需要一行代码来设置PDO模式以获取当前对象,但我不知道如何设置它。请在执行之前尝试使用
bindValue()
。我解决了参数名称的问题。我甚至都不去拿()。我只是试图将fetch设置为fetch到当前对象中$stmt->setFetchMode(PDO::FETCH_类,新凭证);给出:致命错误:未捕获异常“PDOException”,消息为“SQLSTATE[HY000]:一般错误:classname必须是字符串$stmt->setFetchMode(PDO::FETCH_类,“凭证”);给出:致命错误:未捕获异常“PDOException”,消息为“SQLSTATE[HY093]:无效参数编号:未定义参数谢谢。你的回答解决了这个问题。我也很感激有人说我做得不对。我将创建一个单独的类,就像上面显示的那样。一般来说,这是一个好的设计决策吗?我应该创建一个包含该对象的类,然后创建其他类来执行其他操作,还是这特定于通过PDO加载数据?是的,您应该创建执行非常集中的操作的类。这种责任分离的方式是单一责任原则()的应用,它是实体原则()的一部分。在接下来的过程中,您将感谢自己付出的额外努力。VoucherService应该命名为VoucherDao,因为它负责数据访问(在我查找、保存、更新等Dao类中)。