PHP。创建对象的最佳实践
假设我有一个实体(一块石头),我有几个更具体的实体,它们扩展了基本的属性-例如一块会说话的石头,它们有一些不同的属性和方法。石头的所有属性都存储在同一个表中的数据库中。特定对象的所有特定属性都序列化存储在表的字段“specific_options”中。 我有一个“石头”类和一个“会说话的石头”类,它扩展了基本的石头类。 我需要根据从数据库获得的数据创建一个stone对象 使用这种东西的最佳实践是什么 到目前为止,我得到的是:PHP。创建对象的最佳实践,php,oop,Php,Oop,假设我有一个实体(一块石头),我有几个更具体的实体,它们扩展了基本的属性-例如一块会说话的石头,它们有一些不同的属性和方法。石头的所有属性都存储在同一个表中的数据库中。特定对象的所有特定属性都序列化存储在表的字段“specific_options”中。 我有一个“石头”类和一个“会说话的石头”类,它扩展了基本的石头类。 我需要根据从数据库获得的数据创建一个stone对象 使用这种东西的最佳实践是什么 到目前为止,我得到的是: class Stone_Data { ... publ
class Stone_Data {
...
public static function get_item( $id ) {
$sql = 'SELECT * FROM `' . self::$table . '` WHERE `id`=' . ( int ) $id;
$item = self::$db->get_row( $sql );
return $item;
}
...
}
class Stone_Factory {
...
public static function create( $id = null ) {
// if the stone's type is set
if ( !is_null( $id ) && !is_null( $data = Stone_Data::get_item( $id ) ) && !empty( $data['type'] ) ) {
// create a stone of this type
$class_name = ucfirst( $data['type'] ) . '_Stone';
return new $class_name( $data );
}
// otherwise create a basic stone
return new Stone;
}
...
}
class Stone {
private $data = array(
...
'specific_options' => '',
...
);
...
public function __construct( $data = array() ) {
$this->set( $data );
}
...
public function __set( $name, $value ) {
if ( array_key_exists( $name, $this->data ) ) {
// serialize if the value is an array or an object
if ( is_array( $value ) || is_object( $value ) ) {
$value = serialize( $value );
}
$this->data[$name] = $value;
}
}
public function set( $data = array() ) {
foreach ( $data as $key => $value ) {
// serialize if the value is an array or an object
if ( is_array( $value ) || is_object( $value ) ) {
$data[$key] = serialize( $value );
}
}
$this->data = array_merge( $this->data, $data );
return $this;
}
...
}
class Talking_Stone extends Stone {
...
public function __construct( $data = array() ) {
parent::__construct( $data );
// $this->type = 'talking'
$this->specific_options->language = 'French';
...
}
...
}
但不知何故,它感觉不太正确。您希望为此使用存储库类:
class StoneRepository
{
private $stoneFactory;
public function __construct(StoneFactory $factory) {
$this->stoneFactory = $factory;
}
/**
* @param integer $id
* @return Stone
*/
public function findStoneById($id) {
// Fetch your data from the database
$row = ...;
// Use the factory to create a new stone from the data
// that has already been fetched
$stone = $this->stoneFactory->create($row);
// Return the new stone
return $stone;
}
}
这里最大的优点是将数据库逻辑从模型中分离出来。这非常好,因为您可以获得一个干净的模型,而不需要了解数据库。你可以自由地做任何你喜欢的查询,同时保持它们的干净和分离
然后,您可以使用此选项获取具有给定id的石头,例如,您的控制器:
$factory = new StoneFactory();
$repository = new StoneRepository($factory);
$stone = $repository->findStoneById($id);
获取集合
获取集合同样简单:
class StoneRepository
{
...
public function findAllStones() {
// Again, fetch the data
$rows = ...;
// Transform each row into a Stone object
$collection = array_map(function ($row) {
return $this->stoneFactory->create($row);
}, $rows);
return $collection;
}
}
返回具有关系的对象
迟早您可能会想要获取一些相关的对象。这里有几种方法可以采用。最简单的方法是,实际上只需分别获取每种类型的对象,并在控制器中构建模型。例如,如果您想要一个包
对象,其中包含相关的石头
对象:
$bag = $bagRepository->findBagById($bagId);
$stones = $stoneRepository->findStonesByBagId($bagId);
$bag->addStones($stones);
另一种方法是使用join
并在BagRepository
中实际构建Bag
和Stones
。因为它有点复杂,我不打算写在这里
积垢
您也应该使用存储库根据您的模型在数据库中插入/更新/删除数据。同样,它只需添加一个
insert
、update
和delete
方法即可,这些方法接受Stone
对象并将其数据保存在数据库中。漂亮、干净、直接:)嗯。。好像是我一直在找的。谢谢你的回答。还有几个愚蠢的问题:我可以使用repository类来获取Stone集合吗?我该如何处理data manager类(Stone_data),它是数据抽象层?我应该用repository类替换它吗?我是否也应该将repository类用于CRUD操作?基本上是的,是的,是的。我对我的答案进行了一点扩展,让您了解如何获取集合和建立关系。我没有为CRUD添加一个示例,因为它基本上是一样的,但是如果您需要,我会添加它。