为什么要为存储库烦恼
Why bother with repositories
我觉得问这个问题有点愚蠢,因为有很多资源在谈论和解释映射器和存储库,但我似乎无法理解它。所以我创建了一些示例代码来解释我的困惑。请注意,我不知道这段代码是否真的有效,我把它写成一个例子。
这将是实体/class (Quote.php
)
class Quote {
private $id;
private $author;
private $content;
public function getId() {
return $this->id;
}
public function getAuthor() {
return $this->author;
}
public function getContent() {
return $this->content;
}
public function setId(int $id) {
$this->id = $id;
}
public function getAuthor(string $author) {
$this->author = $author;
}
public function setContent(string $content) {
$this->content = $content;
}
}
这就是映射器 (QuoteMapper.php
)
class QuoteMapper {
private $PDO;
public function __construct(PDO $PDO) {
$this->PDO = $PDO;
}
public function find(int $id = null, string $search = null) {
if (!empty($id) && !empty($search)) {
//Search for id and search word
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('search', $search, PDO::PARAM_INT);
$stmt->bindParam('id', $id, PDO::PARAM_INT);
else if (!empty($id)) {
//search for id only
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('id', $id, PDO::PARAM_INT);
} else if (!empty($search)) {
//search for search word only
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('search', $search, PDO::PARAM_INT);
}
$stmt->execute();
$stmt->bindColumn('id', $id);
$stmt->bindColumn('author', $author);
$stmt->bindColumn('content', $content);
$stmt->fetch();
$quote = new Image();
$quote->setId($title);
$quote->setAuthor($source);
$quote->setContent($alternative);
return $image;
}
public function save(Quote $quote) {
//A save function
}
public function delete(Quote $quote) {
//A delete function
}
}
最后但同样重要的是,这将是存储库 (QuoteRepository.php
)
class ArticleRepository {
private $articleMapper;
public function __construct(ArticleMapper $articleMapper) {
$this->articleMapper = $articleMapper;
}
public function find(int $id = null, string $search = null) {
$article = $this->articleMapper->find($id, $search);
return $article;
}
public function save(Quote $quote) {
$this->articleMapper->save($user);
}
public function delete(Quote $quote) {
$this->articleMapper->delete($user);
}
}
据我所知,我的映射器不是 'wrong',因为映射器的目的是执行诸如从持久数据存储(例如 MySQL)获取和设置数据之类的操作
A Data Mapper is a Data Access Layer that performs bidirectional
transfer of data between a persistent data store (often a relational
database) and an in-memory data representation (the domain layer).
From Wikipedia
但我的存储库实际上没有做任何事情。它只是将函数调用传递给映射器?所以我只能假设我的映射器包含应该在存储库中的代码,但那是什么代码?或者我可能完全误解了数据映射器和存储库如何协同工作。
如果我做的任何其他事情是错误的或被认为是不好的做法,我想听听。我真的很想弄明白! :)
DataMapper 是一个将应用程序与具体数据库隔离开来的层。它将对象转换为数据库的记录,并将记录转换为对象。 DataMapper 使我们能够使用数据库并且不知道我们使用的是什么 RDBMS。示例:
interface DataMapperInterface
{
/**
* Find objects by a criteria
*
* @param array $criteria Search params
* @return Quote[] Found entities
*/
public function find(array $criteria);
/**
* Insert an object into a database
*
* @param Quote $object Object that will be inserted
*/
public function insert(Quote $object);
/**
* Update an object date in a database
*
* @param Quote $object Object that will be updated
*/
public function update(Quote $object);
/**
* Remove an object from a database
*
* @param Quote $object Object that will be removed
*/
public function delete(Quote $object);
}
Repository是一个查询构建逻辑的封装层。它使我们能够处理对象集合,而无需注意处理数据库中的任何内容。
class Repository
{
/**
* @var DataMapperInterface Mapper to transform objects
*/
protected $mapper;
/**
* Constructor
*
* @param DataMapperInterface $mapper Mapper to transform objects
*/
public function __construct(DataMapperInterface $mapper)
{
$this->mapper = $mapper;
}
/**
* Find all objects
*
* @return Quote[] Found entities
*/
public function findAll()
{
return $this->mapper->find([]);
}
/**
* Find an object by an identifier
*
* @return Quote[] Found entities
*/
public function findById(integer $id)
{
$criteria = ['id' => $id];
return $this->mapper->find($criteria);
}
/**
* Find objects by an author name
*
* @return Quote[] Found entities
*/
public function findByAuthor($name)
{
$criteria = ['author' => $name];
return $this->mapper->find($criteria);
}
/**
* Save an object into the repository
*/
public function save(Quote $object)
{
if (empty($object->id)) {
$this->mapper->insert($object);
} else {
$this->mapper->update($object);
}
a }
/**
* Remove an object from the repository
*/
public function remove(Quote $object)
{
$this->mapper->delete($object);
}
}
这是一个非常简单的实例,在实际应用程序中一切都更加困难:查询更大,存储库可以与许多其他模式合作(Query Object to query building, Unit of Work to track changes, Identity Map以避免重复加载对象等)
我觉得问这个问题有点愚蠢,因为有很多资源在谈论和解释映射器和存储库,但我似乎无法理解它。所以我创建了一些示例代码来解释我的困惑。请注意,我不知道这段代码是否真的有效,我把它写成一个例子。
这将是实体/class (Quote.php
)
class Quote {
private $id;
private $author;
private $content;
public function getId() {
return $this->id;
}
public function getAuthor() {
return $this->author;
}
public function getContent() {
return $this->content;
}
public function setId(int $id) {
$this->id = $id;
}
public function getAuthor(string $author) {
$this->author = $author;
}
public function setContent(string $content) {
$this->content = $content;
}
}
这就是映射器 (QuoteMapper.php
)
class QuoteMapper {
private $PDO;
public function __construct(PDO $PDO) {
$this->PDO = $PDO;
}
public function find(int $id = null, string $search = null) {
if (!empty($id) && !empty($search)) {
//Search for id and search word
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('search', $search, PDO::PARAM_INT);
$stmt->bindParam('id', $id, PDO::PARAM_INT);
else if (!empty($id)) {
//search for id only
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('id', $id, PDO::PARAM_INT);
} else if (!empty($search)) {
//search for search word only
$stmt = $this->PDO->prepare("SELECT `id`, `author`, `content` FROM `quotes` WHERE `id` = :id AND `content` LIKE :search LIMIT 1");
$stmt->bindParam('search', $search, PDO::PARAM_INT);
}
$stmt->execute();
$stmt->bindColumn('id', $id);
$stmt->bindColumn('author', $author);
$stmt->bindColumn('content', $content);
$stmt->fetch();
$quote = new Image();
$quote->setId($title);
$quote->setAuthor($source);
$quote->setContent($alternative);
return $image;
}
public function save(Quote $quote) {
//A save function
}
public function delete(Quote $quote) {
//A delete function
}
}
最后但同样重要的是,这将是存储库 (QuoteRepository.php
)
class ArticleRepository {
private $articleMapper;
public function __construct(ArticleMapper $articleMapper) {
$this->articleMapper = $articleMapper;
}
public function find(int $id = null, string $search = null) {
$article = $this->articleMapper->find($id, $search);
return $article;
}
public function save(Quote $quote) {
$this->articleMapper->save($user);
}
public function delete(Quote $quote) {
$this->articleMapper->delete($user);
}
}
据我所知,我的映射器不是 'wrong',因为映射器的目的是执行诸如从持久数据存储(例如 MySQL)获取和设置数据之类的操作
A Data Mapper is a Data Access Layer that performs bidirectional transfer of data between a persistent data store (often a relational database) and an in-memory data representation (the domain layer). From Wikipedia
但我的存储库实际上没有做任何事情。它只是将函数调用传递给映射器?所以我只能假设我的映射器包含应该在存储库中的代码,但那是什么代码?或者我可能完全误解了数据映射器和存储库如何协同工作。
如果我做的任何其他事情是错误的或被认为是不好的做法,我想听听。我真的很想弄明白! :)
DataMapper 是一个将应用程序与具体数据库隔离开来的层。它将对象转换为数据库的记录,并将记录转换为对象。 DataMapper 使我们能够使用数据库并且不知道我们使用的是什么 RDBMS。示例:
interface DataMapperInterface
{
/**
* Find objects by a criteria
*
* @param array $criteria Search params
* @return Quote[] Found entities
*/
public function find(array $criteria);
/**
* Insert an object into a database
*
* @param Quote $object Object that will be inserted
*/
public function insert(Quote $object);
/**
* Update an object date in a database
*
* @param Quote $object Object that will be updated
*/
public function update(Quote $object);
/**
* Remove an object from a database
*
* @param Quote $object Object that will be removed
*/
public function delete(Quote $object);
}
Repository是一个查询构建逻辑的封装层。它使我们能够处理对象集合,而无需注意处理数据库中的任何内容。
class Repository
{
/**
* @var DataMapperInterface Mapper to transform objects
*/
protected $mapper;
/**
* Constructor
*
* @param DataMapperInterface $mapper Mapper to transform objects
*/
public function __construct(DataMapperInterface $mapper)
{
$this->mapper = $mapper;
}
/**
* Find all objects
*
* @return Quote[] Found entities
*/
public function findAll()
{
return $this->mapper->find([]);
}
/**
* Find an object by an identifier
*
* @return Quote[] Found entities
*/
public function findById(integer $id)
{
$criteria = ['id' => $id];
return $this->mapper->find($criteria);
}
/**
* Find objects by an author name
*
* @return Quote[] Found entities
*/
public function findByAuthor($name)
{
$criteria = ['author' => $name];
return $this->mapper->find($criteria);
}
/**
* Save an object into the repository
*/
public function save(Quote $object)
{
if (empty($object->id)) {
$this->mapper->insert($object);
} else {
$this->mapper->update($object);
}
a }
/**
* Remove an object from the repository
*/
public function remove(Quote $object)
{
$this->mapper->delete($object);
}
}
这是一个非常简单的实例,在实际应用程序中一切都更加困难:查询更大,存储库可以与许多其他模式合作(Query Object to query building, Unit of Work to track changes, Identity Map以避免重复加载对象等)