【问题标题】:PDO fetch class with foreign key带有外键的 PDO 获取类
【发布时间】:2017-09-19 19:54:17
【问题描述】:

我有课:

class Order {
    private $order_id;
    private $product;
    private $quantity;
}

class Product {
    private $product_id;
    private $name;
    private $price;
}

我也有那些 MySql 表:

orders:
+----------+------------------+----------+
| order_id |     product      | quantity |
+----------+------------------+----------+
| INTEGER  | INT(FOREIGN KEY) | INTEGER  |
+----------+------------------+----------+

products:
+------------+---------+---------+
| product_id |   name  |  price  |
+------------+---------+---------+
|   INTEGER  | VARCHAR | INTEGER |
+------------+---------+---------+

orders.product 是与product.product_id 关联的外键。

我想使用 PDO 从订单表中获取 id 为 123 的订单,并自动将结果存储在 Order 类中。我知道有PDO::fetchObjectPDO::FETCH_CLASS,问题是它们不能递归工作。

我知道我有一个简单的解决方案,即在一个查询中获取 order_idquantity 列,然后在第二个查询中获取产品字段。 有没有办法在一个查询中实现这一点(使用 JOIN)?

【问题讨论】:

  • 问题是它们不能递归工作是什么意思?
  • @Mikey 我想要的结果是一个 Order 对象,其中 product 字段指向一个 Procut 对象,两个对象的字段都具有获取的值。
  • 我很确定没有“简单”的方法可以做到这一点。您必须自己编写该逻辑。解决方案 1 似乎是 IMO 的最佳选择,使用 2 fetchObject() 然后设置订单的产品。解决方案 2 可能适用于 fetchObject(),但您可能会在某处有一些丑陋的逻辑来重建订单的产品。

标签: php mysql pdo


【解决方案1】:

这是对我之前答案的扩展作为另一种选择:

订单:

class Order {
    private $order_id;
    private $product_id;
    private $quantity;

    public function __set($name, $value) {
        if ($this->product === null) {
            $this->product = new Product();
        }
        switch ($name) {
            case 'productId':
                 $this->product->setProductId($value);
                break;
            case 'productName':
                 $this->product->setName($value);
                break;
            case 'productPrice':
                 $this->product->setPrice($value);
                break;
        }
    }
}

产品:

class Product {
    private $product_id;
    private $name;
    private $price;

    public function setProductId($product_id)
    {
        $this->product_id = $product_id;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function setPrice($price)
    {
        $this->price = $price;
    }
}

用法:

$dbh = new PDO(...);
$s = $dbh->prepare('
    SELECT o.*, p.product_id productId, p.name productName, p.price productPrice
    FROM orders o
    JOIN products p ON o.product = p.product_id
    WHERE order_id = :oId
');
$s->bindValue(':oId', 123, PDO::PARAM_INT);
$s->execute();
$result = $s->fetchAll(PDO::FETCH_CLASS, Order::class);

【讨论】:

    【解决方案2】:

    你可以在 Order 类中做点魔法,比如:

    $dbh = new PDO(...);
    
    class Order {
        private $order_id;
        private $product_id;
        // IMPORTANT!
        // If class have `product` property - setter won't be called.
        // private $product;
        private $quantity;
    
        // PDO call this method only in case
        // class doesn't have property with same name like column in db.
        public function __set($name, $value) {
            // If property is product - call setProduct.
            if ($name === 'product') {
                $this->setProduct($value);
            }
        }
    
        public function setProduct($productId)
        {
            /** \PDO IMPORTANT global var here just for example, use better design. */
            global $dbh;
            $s = $dbh->prepare('SELECT * FROM products WHERE product_id = :pId');
            $s->bindParam(':pId', $productId, PDO::PARAM_INT);
            $s->execute();
            $this->product = $s->fetchAll(PDO::FETCH_CLASS, Product::class);
        }
    }
    
    $s = $dbh->prepare('SELECT * FROM orders WHERE order_id = :oId');
    $s->bindValue(':oId', 123, PDO::PARAM_INT);
    $s->execute();
    $result = $s->fetchAll(PDO::FETCH_CLASS, Order::class);
    

    【讨论】:

    • 问题是我不想向数据库发送 2 个查询,因为我可以使用一个查询获取此信息。 ://
    • 添加了另一个答案。
    猜你喜欢
    • 2017-08-27
    • 2016-01-08
    • 2010-12-28
    • 2011-07-05
    • 2021-01-13
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 2014-04-25
    相关资源
    最近更新 更多