[php]Collection和持久化工厂
mapper类中的findbyid($id)可以从数据库中取出指定id的一条数据,映射成一个对象返回。很多时候我们需要返回一个数据集合(findall),那我们就需要一种数据结构来保存这些数据,在需要时映射成对象。既然一条数据映射成一个对象,那么一个数据集合就需要一个对象集合。可以把数据集合和对象集合放在一个类中,这样就方便处理数据到对象的映射了。我们把这个类命名为collection,为了能更好好的访问集合对象,collection子类都实现了iterator接口,使用foreach可以方便访问。
Collection的类结构:

\demo\mapper\Collection:
namespace demo\mapper;
use demo\base\AppException;
use demo\domain\DomainObject;
use demo\mapper\Mapper;
abstract class Collection {
// 保存数据库取出的行数据
protected $raws;
// 保存已映射的对象
protected $objects = array();
// 用于$raws[]到$objects的映射
protected $mapper;
// 当前指针
private $pointer = 0;
// 对象数组总数
private $total = 0;
/**
* @param array $raws 未处理过的数据库数据
* @param Mapper $mapper 用于把$raws映射成对象(createObject)
*/
public function __construct(array $raws = null, Mapper $mapper = null) {
if (!is_null($raws) && !is_null($mapper)) {
$this->raws = $raws;
$this->total = count($raws);
}
$this->mapper = $mapper;
}
/**
* 返回指定$num的数据对象
* @param int $num
*/
public function getRow($num) {
if ($num < 0 || $num >= $this->total) {
return null;
}
// 延迟加载
$this->notifyAccess();
if (isset($this->objects[$num])) {
return $this->objects[$num];
}
if (isset($this->raws[$num])) {
$obj = $this->mapper->createObject($this->raws[$num]);
$this->objects[$num] = $obj;
return $obj;
}
return null;
}
/**
* 添加对象
* @param DomainObject $obj
* @throws AppException
*/
public function add(DomainObject $obj) {
// 类型安全检查
$targetClass = $this->getTargetClass();
if (!($obj instanceof $targetClass)) {
throw new AppException("Object must be {$targetClass}");
}
//
$this->notifyAccess();
$this->objects[$this->pointer++] = $obj;
}
public function current() {
return $this->getRow($this->pointer);
}
public function next() {
$obj = $this->getRow($this->pointer);
if (!is_null($obj)) {
$this->pointer++;
}
return $obj;
}
public function key() {
return $this->pointer;
}
public function rewind() {
$this->pointer = 0;
}
public function valid() {
return !is_null($this->current());
}
/**
* 延迟加载
*/
protected function notifyAccess() {
// 暂时留空
}
protected abstract function getTargetClass();
}\demo\domain:
namespace demo\domain;
use \demo\domain\DomainObject;
interface ClassroomCollection extends \Iterator {
public function add(DomainObject $obj);
}
interface StudentCollection extends \Iterator {
public function add(DomainObject $obj);
}
interface ScoreCollection extends \Iterator {
public function add(DomainObject $obj);
}namespace demo\mapper;
class ClassroomCollection extends Collection
implements \demo\domain\ClassroomCollection {
protected function getTargetClass() {
return '\demo\domain\Classroom';
}
}
class StudentCollection extends Collection
implements \demo\domain\StudentCollection {
protected function getTargetClass() {
return '\demo\domain\Student';
}
}
class ScoreCollection extends Collection
implements \demo\domain\ScoreCollection {
protected function getTargetClass() {
return '\demo\domain\Score';
}
}立即学习“PHP免费学习笔记(深入)”;
现在的结构开始有点复杂了,为了能管理好Mapper和Collection的具体子类,我们可以使用抽象工厂来管理对象的创建。来看看类图:

Magento是一套专业开源的PHP电子商务系统。Magento设计得非常灵活,具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。Magento开源网店系统的特点主要分以下几大类,网站管理促销和工具国际化支持SEO搜索引擎优化结账方式运输快递支付方式客户服务用户帐户目录管理目录浏览产品展示分析和报表Magento 1.6 主要包含以下新特性:•持久性购物 - 为不同的
0
\demo\mapper\PersistanceFatory
namespace demo\mapper;
/**
* 持久化工厂
*/
abstract class PersistanceFactory {
public static function getFactory($targetClass) {
switch ($targetClass) {
case '\demo\domain\Classroom':
return new ClassroomPersistanceFactory();
case '\demo\domain\Student':
return new StudentPersistanceFactory();
case '\demo\domain\Score':
return new ScorePersistanceFactory();
}
}
public abstract function getMapper();
public abstract function getCollection(array $raws = null);
}
class ClassroomPersistanceFactory extends PersistanceFactory {
public function getMapper() {
return new ClassroomMapper();
}
public function getCollection(array $raws = null) {
return new ClassroomCollection($raws, $this->getMapper());
}
}
class StudentPersistanceFactory extends PersistanceFactory {
public function getMapper() {
return new StudentMapper();
}
public function getCollection(array $raws = null) {
return new StudentCollection($raws, $this->getMapper());
}
}
class ScorePersistanceFactory extends PersistanceFactory {
public function getMapper() {
return new ScoreMapper();
}
public function getCollection(array $raws = null) {
return new ScoreCollection($raws, $this->getMapper());
}
}domain包中同样需要Collection对象,但需要注意和mapper中的Collection分离开来。我们可以在domain包中创一个HelperFactory类来当做domain访问mapper的桥梁。

namespace demo\domain;
use demo\mapper\PersistanceFactory;
class HelperFactory {
public static function getCollection($targetClass) {
$fact = PersistanceFactory::getFactory($targetClass);
return $fact->getCollection();
}
public static function getFinder($targetClass) {
$fact = PersistanceFactory::getFactory($targetClass);
return $fact->getMapper();
}
}这样就把domain包和mapper包分离开来了。
Collection有了,那么就来实现Mapper的findAll()吧。
namespace demo\mapper;
use demo\base\AppException;
use \demo\base\ApplicationRegistry;
/**
* Mapper
*/
abstract class Mapper {
//...
/**
* 返回Collection
*/
public function findAll() {
$pStmt = $this->getSelectAllStmt();
$pStmt->execute(array());
$raws = $pStmt->fetchAll(\PDO::FETCH_ASSOC);
$collection = $this->getCollection($raws);
return $collection;
}
/**
* 返回子类Collection
* @param array $raw
*/
public function getCollection(array $raws) {
return $this->getFactory()->getCollection($raws);
}
/**
* 返回子类持久化工厂对象
*/
public function getFactory() {
return PersistanceFactory::getFactory($this->getTargetClass());
}
//....
}例子:
$fact = PersistanceFactory::getFactory('\demo\domain\Classroom');
$mapper = $fact->getMapper();
$classrooms = $mapper->findAll();
foreach ($classrooms as $elem) {
var_dump($elem);
} Colletion能方便管理$raws[]到$objects[]的映射。
PersistanceFactory能管理好mapper包中类对象的创建。
HelperFactory把mapper包和domain包分离开来。
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
C++高性能并发应用_C++如何开发性能关键应用
Java AI集成Deep Java Library_Java怎么集成AI模型部署
Golang后端API开发_Golang如何高效开发后端和API
Python异步并发改进_Python异步编程有哪些新改进
C++系统编程内存管理_C++系统编程怎么与Rust竞争内存安全
Java GraalVM原生镜像构建_Java怎么用GraalVM构建高效原生镜像
Python FastAPI异步API开发_Python怎么用FastAPI构建异步API
C++现代C++20/23/26特性_现代C++有哪些新标准特性如modules和coroutines
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号