【问题标题】:PHP PDO Query in class constructor类构造函数中的 PHP PDO 查询
【发布时间】:2013-07-23 22:04:28
【问题描述】:

我仍在掌握 OOP,但我正在尝试使用由单例数据库连接对象 (#1) 获得的数据创建一个“订单”对象。

我通过获取一个订单号数组然后对其进行迭代(#2)、创建 Order 对象、将订单号传递给类来实现这一点,我希望 Order 类从该类中使用单例数据库连接以获取有关每个订单的更多信息并填充其属性(#​​3)。我的想法是,如果 Order 类在订单标识符之外是“自包含”的,它将更容易维护并且非常灵活。

我知道我可以从 getOrders() 获取数据并将其传递给类,但如果我决定需要另一个字段,我不想修改 50 个不同的查询!

这在一定程度上可行,但如果我有 10 个订单,则只有最后一个订单对象会填充数据库中的数据。我假设数据库连接在它有时间完成和填充它的属性之前被重用?

这里有一些代码...

class Example {
    protected $dBCon;

    #1
    //class constructor
    public function __construct() {
    //connect to SQL database
        $this->dBCon = DB::getInstance();
    }

    #2
    public function getOrders() {
        $orders = array();
        $sql="SELECT ORDNUMBER FROM ORDERS";
        $result = $this->dBCon->executeCommand($sql);
        foreach ($result as $row) {
            $order = new Order($row['ORDNUMBER']);
            $orders[] = $order;
        }
        return $orders;
        }

}

class Order extends Example {
    public $order_number;
    public $customer;
    public $price_list; 

    #3
    public function __construct($order_number) {        
    if ($order_number) {
        //create Order from existing order
        //connect to SQL database
        $this->dBCon = DB::getInstance();
        $sql = "SELECT * FROM ORDERS WHERE ORDNUMBER = ?";
        $result = $this->dBCon->executePreparedStatement($sql, array($order_number));
        $this->order_number = $order_number;
        foreach ($result as $row) {             
            $this->customer = new Customer($row['CUSTOMER']);
            $this->price_list = $row['PRICELIST'];
        }
    }
}

所以调用 getOrders() 会给我例如 10 个订单对象,但只有最后一个包含任何数据。您还可以看到,我想对每个订单的 Customer 对象执行类似的操作。

我也尝试创建数据库连接的新实例,这确实为每个创建的对象获取数据,但是我知道我可能会创建很多数据库连接!

这是解决这个问题的正确方法还是我完全搞错了 OOP 棒的一端!?

【问题讨论】:

  • 类构造函数不应该做任何实际工作,只是设置。除了将传入的参数分配给成员变量之外,它们通常不应该做任何事情。如果可以避免的话,你绝对不应该在构造函数中进行查询。您的子类应该有一个 getOrder 方法,该方法执行实际查询,并在调用构造函数后由消费代码调用。
  • 谢谢@GordonM,又学到了一课!把它放在那里感觉很不对,但我正在尽我最大的努力来获得一个一击解决方案来填充课程。我移动了所有东西 bar $this->order_number = $order_number;到 Order->getOrder() 方法并在访问每个对象时调用它。它只是记住需要调用 getOrder() 才能填充它!

标签: php class oop pdo instantiation


【解决方案1】:

我会先让Order 变得非常简单:

class Order
{
    public $order_number;
    public $customer;
    public $price_list; 
}

它对 SQL 或任何形式的数据库一无所知。然后,您可以选择一两步加载这些对象;现在让我们一步一步完成。

class OrderGateway
{
    public static function getOrders(PDO $db)
    {
        $orders = array();

        $stmt = $db->query('SELECT * FROM `orders`');
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $order = new Order();
            $order->order_number = $row['ORDNUMBER'];
            $order->customer = new Customer($row['CUSTOMER']);
            $order->price_list = $row['PRICELIST'];

            $orders[] = $order;
        }

        return $orders;
    }
}

$orders = OrderFactory::getOrders($db);

这可以通过引入位于网关和数据类之间的数据映射器类来进一步改进。您可以在搜索“数据映射器模式”时阅读相关内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 2018-10-08
    • 2013-08-17
    • 2016-09-02
    • 1970-01-01
    相关资源
    最近更新 更多