Это общая структура для модели отображения доменов?

Надеюсь, я спрашиваю об этом на правильном стеке форума обмена. Если нет, пожалуйста, дайте мне знать, и я спрошу где-нибудь еще. Я также спрашивал о Code Review, но сообщество кажется намного менее активным.

Так как я самостоятельно изучил PHP и все программирование в целом, я только недавно узнал о «преобразователях данных», которые позволяют передавать данные в классы без того, чтобы эти классы знали, откуда поступают данные. Я прочитал некоторые положительные стороны использования картографов и почему они облегчают выполнение обновлений позже, однако я действительно изо всех сил пытаюсь найти рекомендуемый способ использования картографов и их макетов в структуре каталогов.

Давайте предположим, что у нас есть простое приложение, целью которого является вывод имени и фамилии пользователя.

То, как я использовал / создавал мапперы (а также структуру файла, выглядит следующим образом):

index.php

include 'classes/usermapper.php';
include 'classes/user.php';

$user = new User;
$userMapper = new userMapper;

try {
$user->setData([
$userMapper->fetchData([
'username'=>'peter1'
])
]);
} catch (Exception $e) {
die('Error occurred');
}

if ($user->hasData()) {
echo $user->fullName();
}

классы / user.php

class User {
private $_data;

public function __construct() { }

public function setData($userObject = null) {
if (!$userObject) { throw new InvalidArgumentException('No Data Set'); }
$this->_data = $dataObject;
}

public function hasData() {
return (!$this->_data) ? false : true;
}

public function fullName() {
return ucwords($this->_data->firstname.' '.$this->_data->lastname);
}
}

классы / usermapper.php

class userMapper {
private $_db;

public function __construct() { $this->_db = DB::getInstance(); }

public function fetchData($where = null) {
if (!is_array($where)) {
throw new InvalidArgumentException('Invalid Params Supplied');
}

$toFill = null;
foreach($where as $argument=>$value) {
$toFill .= $argument.' = '.$value AND ;
}

$query = sprintf("SELECT * FROM `users` WHERE %s ", substr(rtrim($toFill), 0, -3));


$result = $this->_db->query($query); //assume this is just a call to a database which returns the results of the query

return $result;
}
}

С пониманием того, что таблица users содержит имя пользователя, имя и фамилию, а также отсутствие множества проверок очистки, почему удобно использовать мапперы?

Это очень долгий способ получения данных, и при условии, что пользователи — это не все, а вместо того, что у заказов, платежей, билетов, компаний и многих других есть соответствующие сопоставители, кажется, что не стоит создавать только один сопоставитель и внедрять его. везде в каждом классе.
Это позволяет структуре папок выглядеть намного лучше, а также означает, что код повторяется не так часто.

Примеры мапперов выглядят одинаково в каждой строке таблицы, из которой извлекаются данные.

Поэтому мой вопрос. Так должны выглядеть сопоставители данных в «сопоставителях модели предметной области», и если нет, то как можно улучшить мой код? Во-вторых, нужна ли эта модель во всех случаях необходимости извлечения данных из базы данных, независимо от размера класса, или эта модель должна использоваться только там, где user.php класс в этом случае очень большой?

Заранее благодарю за помощь.

0

Решение

Data Mapper полностью отделяет доменные объекты от постоянного хранилища (базы данных) и предоставляет методы, специфичные для операций на уровне домена. Используйте его для передачи данных из домена в базу данных и наоборот. Внутри метода запрос к базе данных обычно выполняется, и результат затем сопоставляется (гидратируется) с объектом домена или списком объектов домена.

Пример:

Базовый класс: Mapper.php

abstract class Mapper
{
protected $db;

public function __construct(PDO $db)
{
$this->db = $db;
}
}

Файл: BookMapper.php

class BookMapper extends Mapper
{
public function findAll(): array
{
$sql = "SELECT id, title, price, book_category_id FROM books;";
$statement = $this->db->query($sql);

$items = [];
while ($row = $statement->fetch()) {
$items[] = new BookEntity($row);
}

return $items;
}

public function findByBookCategoryId(int $bookCategoryId): array
{
$sql = "SELECT id, title, price, book_category_id
FROM books
WHERE book_category_id = :book_category_id;";

$statement = $this->db->prepare($sql);
$statement->execute(["book_category_id" => $bookCategoryId]);

$items = [];
while ($row = $statement->fetch()) {
$items[] = new BookEntity($row);
}

return $items;
}

/**
* Get one Book by its ID
*
* @param int $bookId The ID of the book
* @return BookEntity The book
* @throws RuntimeException
*/
public function getById(int $bookId): BookEntity
{
$sql = "SELECT id, title, price, book_category_id FROM books
WHERE id = :id;";

$statement = $this->db->prepare($sql);

if (!$result = $statement->execute(["id" => $bookId])) {
throw new DomainException(sprintf('Book-ID not found: %s', $bookId));
}

return new BookEntity($statement->fetch());
}

public function insert(BookEntity $book): int
{
$sql = "INSERT INTO books SET title=:title, price=:price, book_category_id=:book_category_id";
$statement = $this->db->prepare($sql);

$result = $statement->execute([
'title' => $book->getTitle(),
'price' => $book->getPrice(),
'book_category_id' => $book->getBookCategoryId(),
]);

if (!$result) {
throw new RuntimeException('Could not save record');
}

return (int)$this->db->lastInsertId();
}
}

Файл: BookEntity.php

class BookEntity
{
/** @var int|null */
protected $id;

/** @var string|null */
protected $title;

/** @var float|null */
protected $price;

/** @var int|null */
protected $bookCategoryId;

/**
* Accept an array of data matching properties of this class
* and create the class
*
* @param array|null $data The data to use to create
*/
public function __construct(array $data = null)
{
// Hydration (manually)
if (isset($data['id'])) {
$this->setId($data['id']);
}
if (isset($data['title'])) {
$this->setTitle($data['title']);
}
if (isset($data['price'])) {
$this->setPrice($data['price']);
}
if (isset($data['book_category_id'])) {
$this->setBookCategoryId($data['book_category_id']);
}
}

/**
* Get Id.
*
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}

/**
* Set Id.
*
* @param int|null $id
* @return void
*/
public function setId(?int $id): void
{
$this->id = $id;
}

/**
* Get Title.
*
* @return null|string
*/
public function getTitle(): ?string
{
return $this->title;
}

/**
* Set Title.
*
* @param null|string $title
* @return void
*/
public function setTitle(?string $title): void
{
$this->title = $title;
}

/**
* Get Price.
*
* @return float|null
*/
public function getPrice(): ?float
{
return $this->price;
}

/**
* Set Price.
*
* @param float|null $price
* @return void
*/
public function setPrice(?float $price): void
{
$this->price = $price;
}

/**
* Get BookCategoryId.
*
* @return int|null
*/
public function getBookCategoryId(): ?int
{
return $this->bookCategoryId;
}

/**
* Set BookCategoryId.
*
* @param int|null $bookCategoryId
* @return void
*/
public function setBookCategoryId(?int $bookCategoryId): void
{
$this->bookCategoryId = $bookCategoryId;
}
}

Файл: BookCategoryEntity.php

class BookCategoryEntity
{
const FANTASY = 1;
const ADVENTURE = 2;
const COMEDY = 3;

// here you can add the setter and getter methods
}

Структура таблицы: schema.sql

CREATE TABLE `books` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`price` decimal(19,2) DEFAULT NULL,
`book_category_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `book_category_id` (`book_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `book_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `book_categories` */

insert  into `book_categories`(`id`,`title`) values (1,'Fantasy');
insert  into `book_categories`(`id`,`title`) values (2,'Adventure');
insert  into `book_categories`(`id`,`title`) values (3,'Comedy');

использование

// Create the database connection
$host = '127.0.0.1';
$dbname = 'test';
$username = 'root';
$password = '';
$charset = 'utf8';
$collate = 'utf8_unicode_ci';
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset COLLATE $collate"];

$db = new PDO($dsn, $username, $password, $options);

// Create the data mapper instance
$bookMapper = new BookMapper($db);

// Create a new book entity
$book = new BookEntity();
$book->setTitle('Harry Potter');
$book->setPrice(29.99);
$book->setBookCategoryId(BookCategoryEntity::FANTASY);

// Insert the book entity
$bookId = $bookMapper->insert($book);

// Get the saved book
$newBook = $bookMapper->getById($bookId);
var_dump($newBook);

// Find all fantasy books
$fantasyBooks = $bookMapper->findByBookCategoryId(BookCategoryEntity::FANTASY);
var_dump($fantasyBooks);
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector