假设您像这样组织对象:
为了初始化整个建筑对象(包括关卡、房间、物品),您必须提供数据库层类来完成这项工作。获取建筑物树视图所需的所有内容的一种方法是:
(放大浏览器以获得更好的视图)
构建将根据作为参数提供给 initializeById 方法的映射器使用适当的数据初始化自身。这种方法也可以在初始化关卡和房间时起作用。(注意:在初始化整个建筑物时重用那些 initializeById 方法会导致大量的数据库查询,所以我使用了一点结果索引技巧和 SQL IN opetator)
class RoomMapper implements RoomMapperInterface {
public function fetchByLevelIds(array $levelIds) {
foreach ($levelIds as $levelId) {
$indexedRooms[$levelId] = array();
}
//SELECT FROM room WHERE level_id IN (comma separated $levelIds)
// ...
//$roomsData = fetchAll();
foreach ($roomsData as $roomData) {
$indexedRooms[$roomData['level_id']][] = $roomData;
}
return $indexedRooms;
}
}
现在假设我们有这个数据库模式
最后是一些代码。
建造
class Building implements BuildingInterface {
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var LevelInterface[]
*/
private $levels = array();
private function setData(array $data) {
$this->id = $data['id'];
$this->name = $data['name'];
}
public function __construct(array $data = NULL) {
if (NULL !== $data) {
$this->setData($data);
}
}
public function addLevel(LevelInterface $level) {
$this->levels[$level->getId()] = $level;
}
/**
* Initializes building data from the database.
* If all mappers are provided all data about levels, rooms and items
* will be initialized
*
* @param BuildingMapperInterface $buildingMapper
* @param LevelMapperInterface $levelMapper
* @param RoomMapperInterface $roomMapper
* @param ItemMapperInterface $itemMapper
*/
public function initializeById(BuildingMapperInterface $buildingMapper,
LevelMapperInterface $levelMapper = NULL,
RoomMapperInterface $roomMapper = NULL,
ItemMapperInterface $itemMapper = NULL) {
$buildingData = $buildingMapper->fetchById($this->id);
$this->setData($buildingData);
if (NULL !== $levelMapper) {
//level mapper provided, fetching bulding levels data
$levelsData = $levelMapper->fetchByBuildingId($this->id);
//indexing levels by id
foreach ($levelsData as $levelData) {
$levels[$levelData['id']] = new Level($levelData);
}
//fetching room data for each level in the building
if (NULL !== $roomMapper) {
$levelIds = array_keys($levels);
if (!empty($levelIds)) {
/**
* mapper will return an array level rooms
* indexed by levelId
* array($levelId => array($room1Data, $room2Data, ...))
*/
$indexedRooms = $roomMapper->fetchByLevelIds($levelIds);
$rooms = array();
foreach ($indexedRooms as $levelId => $levelRooms) {
//looping through rooms, key is level id
foreach ($levelRooms as $levelRoomData) {
$newRoom = new Room($levelRoomData);
//parent level easy to find
$levels[$levelId]->addRoom($newRoom);
//keeping track of all the rooms fetched
//for easier association if item mapper provided
$rooms[$newRoom->getId()] = $newRoom;
}
}
if (NULL !== $itemMapper) {
$roomIds = array_keys($rooms);
$indexedItems = $itemMapper->fetchByRoomIds($roomIds);
foreach ($indexedItems as $roomId => $roomItems) {
foreach ($roomItems as $roomItemData) {
$newItem = new Item($roomItemData);
$rooms[$roomId]->addItem($newItem);
}
}
}
}
}
$this->levels = $levels;
}
}
}
等级
class Level implements LevelInterface {
private $id;
private $buildingId;
private $number;
/**
* @var RoomInterface[]
*/
private $rooms;
private function setData(array $data) {
$this->id = $data['id'];
$this->buildingId = $data['building_id'];
$this->number = $data['number'];
}
public function __construct(array $data = NULL) {
if (NULL !== $data) {
$this->setData($data);
}
}
public function getId() {
return $this->id;
}
public function addRoom(RoomInterface $room) {
$this->rooms[$room->getId()] = $room;
}
}
房间
class Room implements RoomInterface {
private $id;
private $levelId;
private $number;
/**
* Items in this room
* @var ItemInterface[]
*/
private $items;
private function setData(array $roomData) {
$this->id = $roomData['id'];
$this->levelId = $roomData['level_id'];
$this->number = $roomData['number'];
}
private function getData() {
return array(
'level_id' => $this->levelId,
'number' => $this->number
);
}
public function __construct(array $data = NULL) {
if (NULL !== $data) {
$this->setData($data);
}
}
public function getId() {
return $this->id;
}
public function addItem(ItemInterface $item) {
$this->items[$item->getId()] = $item;
}
/**
* Saves room in the databse, will do an update if room has an id
* @param RoomMapperInterface $roomMapper
*/
public function save(RoomMapperInterface $roomMapper) {
if (NULL === $this->id) {
//insert
$roomMapper->insert($this->getData());
} else {
//update
$where['id'] = $this->id;
$roomMapper->update($this->getData(), $where);
}
}
}
物品
class Item implements ItemInterface {
private $id;
private $roomId;
private $name;
private function setData(array $data) {
$this->id = $data['id'];
$this->roomId = $data['room_id'];
$this->name = $data['name'];
}
public function __construct(array $data = NULL) {
if (NULL !== $data) {
$this->setData($data);
}
}
/**
* Returns room id (needed for indexing)
* @return int
*/
public function getId() {
return $this->id;
}
}