使用mysql对象的迭代器


Iterator on MySQL-using objects

我正在考虑这样的问题…假设我们有一个类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有相同的加载接口(function load()),但如果我想迭代People中的$ People来加载他们的数据,那么这将导致maaaaany查询,如:

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

如果想加载1000个,那么就会出现boom:)。

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

  1. 我必须在我添加到People中的每个Person对象中保持使用依赖注入。这是违反DRY规则,只是不好看。

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

我建议在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;
    }
  }
}

如果像Symfony2 (http://symfony.com/doc/2.0/book/service_container.html)那样构建服务,只需添加方法即可。在"person"上使用"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
  }
}