Зачем возиться с репозиториями - PullRequest
0 голосов
/ 14 января 2019

Я чувствую себя немного глупо, задавая этот вопрос, потому что есть много ресурсов, говорящих и объясняющих картографы и репозитории, но я, кажется, не могу разобраться с этим. Итак, я создал пример кода, чтобы объяснить мою путаницу. Обратите внимание, что я не знаю, сработает ли этот код, я написал это в качестве примера.

Это будет сущность / класс (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);
  }
}

Как я понимаю, мой маппер не является "неправильным", так как его цель состоит в том, чтобы делать такие вещи, как получение и установка данных из постоянного хранилища данных (например, MySQL)

Data Mapper - это уровень доступа к данным, который выполняет двунаправленный передача данных между постоянным хранилищем данных (часто реляционным база данных) и представление данных в памяти (уровень домена). От Википедия

Но мой репозиторий на самом деле ничего не делает. Он просто передает вызов функции в маппере? Поэтому я могу только предположить, что мой маппер содержит код, который должен быть в хранилище, но какой это будет код? Или, может быть, я совершенно не понял, как сопоставители данных и репозитории будут работать вместе.

Если есть какие-то другие поступки, которые я совершил, которые являются неправильными или считаются плохой практикой, я хотел бы услышать это. Я действительно пытаюсь понять это! :)

1 Ответ

0 голосов
/ 13 февраля 2019

DataMapper - это слой для изоляции приложения от конкретной базы данных. Он преобразует объект в запись базы данных, а запись в объект. DataMapper дает нам возможность работать с базой данных и не знать, какую СУБД мы используем. Пример:

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);
}

Репозиторий - это слой для инкапсуляции логики построения запроса. Это дает нам возможность работать с коллекцией объектов и ничего не знать о работе с базой данных.

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);
   }
}

Это очень простой пример, и все сложнее в реальном приложении: запросы больше, репозиторий может взаимодействовать со многими другими шаблонами ( Объект запроса для построения запроса, Единица работы для отслеживания изменений, Identity Map , чтобы избежать повторной загрузки объектов и т. Д.)

...