我用PHP编程已经有几年了,过去也曾采用过自己的方法来处理应用程序中的数据。
我在过去构建过自己的MVC,并且对php中的OOP有一个合理的理解,但我知道我的实现还需要一些认真的工作。
在过去,我在模型和数据库表之间使用is-a关系。在做了一些研究之后,我现在知道这并不是最好的前进道路。据我所知,我应该创建不真正关心底层数据库(或任何要使用的存储机制)的模型,而只关心它们的操作和数据。
由此,我确定了我可以创建模型,例如,一个Person和this person对象可以有一些孩子(人类孩子),这些孩子也是一个数组中保存的Person对象(使用addPerson和removePerson方法,接受一个Person对象)。
然后我可以创建一个PersonMapper,我可以用它来获取一个具有特定'id‘的人,或者用来拯救一个人。
然后,这可以在查找表中查找关系数据,并为已被请求的人员创建相关联的子对象(如果有),并同样将数据保存在保存命令的查找表中。
这是我现在所知的极限……
如果我想要对具有不同楼层和不同房间的建筑进行建模,该怎么办?如果我想在那些房间里放些东西怎么办?
是否要为建筑物、楼层、房间和项目创建类
具有以下结构。
建筑物可以有一个或多个级别对象放在一个数组中级别可以有一个或多个房间对象放在一个数组中房间可以有一个或多个项目对象放在一个数组中
每个类的映射器和具有更高级别映射器的映射器使用子映射器来填充数组(根据顶级对象的请求或根据请求延迟加载)
这似乎紧密地耦合了不同的对象,尽管是在一个方向上(即。楼层不一定要在建筑物中,但建筑物可以有标高)
这是正确的做法吗?
在视图中,我想要显示一个具有选择级别的选项的建筑,然后显示具有选择房间等选项的级别。但我可能也想要显示一个树状结构的项目在建筑物中,以及他们是在什么水平和房间。
我希望这是有意义的。当oop的一般概念似乎是分离事物时,我只是在为相互嵌套对象的概念而苦苦挣扎。
如果有人能帮上忙,那将是非常有用的。
发布于 2013-02-11 12:18:53
假设你这样组织你的对象:

为了初始化整个建筑对象(具有层、房间、项目),你必须提供db层类来完成这项工作。获取建筑物树状视图所需的所有内容的一种方法是:
(缩放浏览器以获得更好的视图)

构建将根据作为参数提供给initializeById方法的映射器,使用适当的数据对自身进行初始化。初始化标高和房间时,此方法也适用。(注意:在初始化整个构建时重用这些initializeById方法将导致大量的db查询,所以我使用了一些结果索引技巧和SQL 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;
}
}现在让我们假设我们有这个db模式

最后是一些代码。
构建
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;
}
}https://stackoverflow.com/questions/12373189
复制相似问题