【问题标题】:PHP Object : Loop on product listPHP对象:产品列表上的循环
【发布时间】:2012-09-23 16:17:07
【问题描述】:

我有一个快速的:我是 PHP 对象的初学者,我有一个包含我所有产品的产品表。

我的产品也有一个类(带有一个用我的产品的所有参数填充我的实例的构造函数)。

假设我想要一个我所有产品的列表,我应该为我的产品列表创建一个单独的类,还是创建一个函数来创建我的产品类的新实例?

我现在并没有真正得到它的好处,因为如果我必须执行与我的类查询完全相同的查询,它就没用了吗?

感谢您的提示!

更新

谢谢各位!这对我来说仍然很复杂,但这是我所做的(谈论书籍)试图听从你的建议。

我创建了一个 DAO。在这个 DAO 中,我有两个静态函数返回书籍列表或一本书,还有一个创建书籍对象的静态函数。

使用这种方法,我仍然有 2 个查询(一个用于列表,一个用于单本书)。我觉得这是错误的,但感谢任何帮助:)

class bookDAO {

    public static function getBooks() {
        $books = array();
        $db = databaseConnection::getInstance();
        $query = $db->query("SELECT * FROM books");
        while($row = $query->fetchObject()) {
            $book = self::createBookFromRow($row);
            $books[] = $book;
        }
        return $books;
    }

    public static function getBook($id){
        $db = databaseConnection::getInstance();
        $query = $db->prepare("SELECT * FROM books WHERE id=:id");
        $query->execute(array(":id"=>$id));
        $row = $query->fetchObject();
        $book = self::createBookFromRow($row);
        return $book;
    }

    private static function createBookFromRow($row) {
        $book = new book($row);
        return $book;
    }

}

【问题讨论】:

    标签: php list class object loops


    【解决方案1】:

    在这种情况下创建对象数组是很常见的。

    例如:

    $products = array();
    foreach($results as $result) {
      $products[] = new Product($result);
    }
    print_r($products);
    

    【讨论】:

    • 如果 Product 对象执行 db-query 这个方法对于 mysql 来说会非常缓慢和痛苦
    • 我提供的只是一个示例,实际上是伪代码,基于 OP 提供的有限描述。
    【解决方案2】:

    您的 Product 类不应该执行任何查询,将其分成 DAO,例如ProductDAO

    class ProductDAO
    {
      function static getProducts()
      {
         //Your query here: PDO, MySQLi, MySQL etc
        $products = array(); //to store array of products
    
        while($row = mysql_fetch_assoc($result))
        {
           $product = createProductFromRow($row);
    
           $products[] = $product;
        }
    
        return $products;
    }
    
       private static function createProductFromRow($row)
       {
       $product = new Product();
       $product->setId($row["id"]);
       $product->setName($row["Name"]);
       //etc
    
       return $product; 
       }
    }
    

    来自您的页面

      $products = ProductDAO::getProducts();
    
      foreach($products as $p)
      {
         echo ($p->getName() + '<br />');
      }
    

    【讨论】:

      【解决方案3】:

      您可以简单地添加一个数组。或者,如果您想向产品列表中添加一些方法,您可以实现如下内容:

      class Products
      {
          private $productFactory;
      
          private $products = array();
      
          public function __construct(ProductFactory $productFactory) {
              $this->productFactory = $productFactory;
          }
      
          public function addProduct($product)
          {
              $this->products[] = $this->productFactory->build($product);
          }
      
          public function addProducts($products)
          {
              foreach ($products as $product) {
                  $this->addProduct($product);
              }
          }
      
          // do soemthing with all products
          public function changeProducts()
          {
              foreach($this->products as $product) {
                  $product->changeSpec('new spec value');
              }
          }
      }
      
      class Product
      {
          private $someSpec;
      
          public function __construct($spec)
          {
              $this->someSpec = $spec;
          }
      
          public function changeSpec($spec) {
              $this->someSpec = $spec;
          }
      }
      
      class ProductFactory
      {
          public function build($spec) {
              return new Product($spec);
          }
      }
      
      // build the productslist object
      $productFactory = new ProductFactory();
      $products = new Products($productFactory);
      $products->addProducts(array(
          'some spec of product1',
          'some spec of product2',
      ));
      

      请注意,我手动添加了产品,但这也可能是来自某些持久存储机制(例如数据库)的记录集。或者也许更好地注入一些访问数据库以检索产品的类。不要在 Product / Products 类中进行任何查询。如果你这样做了,那么你就是tightly coupling 某些东西(数据库),这使得测试变得非常困难。除此之外,你还违反了SRP

      请注意,我创建了一个工厂来创建 Product 类的新实例。这样您就没有将Product 类与Products 类紧密耦合。如果您想进行单元测试,这使得模拟 Product 类变得更加容易。

      更新

      您可以对Products 类做的另一件事是让它实现Iterator interface,这样您还可以根据需要循环遍历产品。

      【讨论】:

      • 忘记了 Products 中的构造函数?
      【解决方案4】:

      将保存所有产品引用的产品类

      class Products {
      
          static private $store = array();
      
          static public function save(Product $object)
          {
              self::$store[] = $object;
          }
      
          static public function getAll()
          {
              return self::$store;
          }
      
      }
      

      将每个 Product 引用保存到 Products 类

      最简单的方法是在您的 Product 构造函数中进行。

      # your Product class
      class Product {
      
          public function __construct()
          {
              # your stuff here..
      
              # save reference of current Product to the Products
              Products::save($this);
          }
      
      }
      

      您对产品的初始化

      这只是为了测试,在这里使用你的逻辑来初始化产品对象。

      new Product;
      new Product;
      new Product;
      

      遍历所有产品

      foreach (Products::getAll() as $product) {
          var_dump($product);
      }
      

      【讨论】:

      • 我不会,但我确实想对此投反对票,因为这将很难进行单元测试,因为所有 static 和紧密耦合。
      • 你将如何在Products 类的构造函数中模拟出Products::save($this);?此外,您的构造函数正在做的工作从来都不是一个好主意(除了紧密耦合之外)。
      • 另请参阅我的semi related answer,以更深入地解释为什么它不是(恕我直言)最佳解决方案。
      • sebastian-bergmann.de/archives/… ?你是说“静态方法是可测试性的死亡”,我们不应该使用它们吗?
      • +1 @PeeHaa 所说的。如果我看到它,我会逃避这样的设计。
      猜你喜欢
      • 2015-11-29
      • 2012-09-10
      • 2019-08-30
      • 2015-05-06
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      相关资源
      最近更新 更多