【问题标题】:Iterator on MySQL-using objects使用 MySQL 的对象上的迭代器
【发布时间】:2013-03-25 10:12:44
【问题描述】:

我正在考虑这样的问题......假设我们有一个类 Person:

   class Person {  
    private $iPersonId;
    private $sName;  
    private $sLastName;  
    private $rConn;


public function __construct($rConn, $iPersonId) {
$this->rConn = $rConn;
$this->iPersonId = $iPersonId;
}

   public function load() {
      // load name and last name using the $rConn object and $iPersonId
   }  
   }

现在我们想对很多人执行一些操作,所以我们编写了一个新类:

class People {

private $aPeople = array();

public function addPerson(Person $oPerson) {
// ...
}

public function loadPeople() {
// PROBLEM HERE //
}

}

现在有两个问题: 1. Person 和 People 具有相同的加载接口(函数 load()),但如果我想在 People 中迭代 $aPeople 以加载他们的数据,那么这将导致 maaaaany 查询,例如:

SELECT * FROM people WHERE id = 1
SELECT * FROM people WHERE id = 2
SELECT ......
.....
....

如果想加载 1000 个,那么事情就会变得繁荣起来 :)。

如何设计此代码以在一个查询中加载所有用户? (在)

  1. 我必须在添加到 People 的每个 Person 对象中继续使用依赖注入。这违反了 DRY 规则,而且看起来不太好。

亲爱的用户,设计这段代码的更好方法是什么?

【问题讨论】:

  • loadPeople()的内容是什么?
  • foreach($aPeople as $oPerson)

标签: php mysql oop


【解决方案1】:

我建议在 People 中使用静态方法来加载大量人员。 这也需要你重写构造函数,或者添加另一个方法来初始化其他数据。

class Person {  
  protected $_data
  protected $rConn;


  public function __construct($rConn, $iPersonId) {
    $this->rConn = $rConn;
    $this->_data = array();
    $this->_data['id'] = $iPersonId;
  }

  public function load() {
    // load name and last name using the $rConn object and $iPersonId
  }

  // under the assumption, that $rConn is a mysqli connection
  // if not rewrite the specific section
  // also there is no injection protection or error handling in here
  // this is just a workflow example, not good code!
  public static function loadPeople($ids) {
    $res = $rConn->query("select * from people where id in (" . implode(',', $ids) . ")");
    $people = array();
    while ($row = $res->fetch_assoc()) {
      $p = new People($rConn, $row['id']);
      $p->setData($row);
      $people[] = $p;
    }
    $res->free();
    return $people;
  }

  public function setData($data) {
    foreach ($data as $key => $value {
      $this->_data[key] = $value;
    }
  }
}

【讨论】:

    【解决方案2】:

    如果您在 Symfony2 (http://symfony.com/doc/2.0/book/service_container.html) 中构建服务,则只需添加方法即可。在“人”上使用“load()”听起来不正确。它本身加载了什么?让您的对象或实体访问数据库也是一种不好的做法,这会导致不必要的依赖关系。

    • 你的实体或对象不应该有一个函数来加载自己,不好的做法。让其他东西管理实体或对象。
    • 不要建立导致混乱的依赖关系,保持对象为自己的目的。 PersonEntity 永远不应该知道有关数据库连接或 EntityManager 的任何信息
    • 构建您的代码,以便您可以将其移至另一个项目,而不会破坏 Composer。 http://getcomposer.org/

    作为我在 symfony2 中如何做的例子

    class PeopleService
    {
      private $em;
    
      /**
       * @param EntityManager $em
       */
      public function __construct(EntityManager $em)
      {
        $this->em = $em;
      }
    
      /**
       * @param int $id
       * @return Person
       */
      public function loadPerson($id)
      {
        // do something and return 1 person
        return $this->em->find('MyBundleNamspace:Person', $id);
      }
    
      /**
       * @return array of Person objects
       */
      public function loadPeople()
      {
        // do something and return an array with persons
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2011-11-22
      • 2017-12-18
      • 1970-01-01
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多