extension_dir = c:\php\ext\
<?php
namespace App\DTO;
class PostDTO
{
/** @var string */
private $name;
/** @var string */
private $description;
/** @var string */
private $text;
public function __construct(string $name, string $description, string $text)
{
$this->name = $name;
$this->description = $description;
$this->text = $text;
}
public function getName()
{
return $this->name;
}
public function getDescription()
{
return $this->description;
}
public function getText()
{
return $this->text;
}
}
$query = $em->createQuery('SELECT NEW App\DTO\PostDTO(p.name, p.description, p.text) FROM App\Entity\Post p');
$users = $query->getResult(); // array of PostDTO
Product
в строке 123 вы используете @ORM\ManyToOne(targetEntity="Category", mappedBy="product")
$this->solutions
должно устанавливаться через конструктор, потому вам не составит труда заинжектить это состояние в тестируемый объект.protected function setPrivateProperty(object $object, string $propertyName, $value): void
{
$reflectionClass = new \ReflectionClass(get_class($object));
$property = $reflectionClass->getProperty($propertyName);
$property->setAccessible(true);
$property->setValue($object, $value);
$property->setAccessible(false);
}
class System
{
// Не важно, как оно будет заполнено, важно,
// что в методе мы проверяем некоторые значения
// и мы создадим ниже в тестах эти ситуации разными тест-кейсами
private $solutions;
public function checkRecords(): string
{
if (count($this->solutions) === 3) {
return 'full';
}
if (count($this->solutions) === 6) {
return 'overflow';
}
throw new IncorrectCountException('Incorrect solutions count.');
}
}
public function testCheckRecordsFull(): void
{
// 3 элемента
$data = [1, 2, 3];
$system = new System();
$this->setPrivateProperty($system, 'solutions', $data);
$status = $system->checkRecords();
$this->assertEquals('full', $status);
}
public function testCheckRecordsOverFlow(): void
{
// 6 элементов
$data = [1, 2, 3, 4, 5, 6];
$system = new System();
$this->setPrivateProperty($system, 'solutions', $data);
$status = $system->checkRecords();
$this->assertEquals('overflow', $status);
}
public function testCheckRecordsIncorrectCOunt(): void
{
// сколько-то элементов, но не 3 и не 6
$data = [1];
$system = new System();
$this->setPrivateProperty($system, 'solutions', $data);
$this->expectException(IncorrectCountException::class);
$system->checkRecords();
}
И в будущем удобно будет тестировать ?
getMobileOpinionList()
getDefaultOpinionList()
$em->flush()
- вы с радостью согласитесь и, возможно, тогда поймёте что даёт Doctrine разработчику.ifnull()
в DQL становится довольно бессмысленной конструкцией т.к. эта функция довольно слабо применима к объектам.class Tweet
{
private $id;
private $content;
public function __construct(int $id, string $content)
{
$this->id = $id;
$this->content = $content;
}
public function getId(): int
{
return $this->id;
}
public function getContent(): string
{
return $this->content;
}
public function setContent(string $content): void
{
$this->content = $content;
}
}
CREATE TABLE tweets (
id INTEGER PRIMARY KEY,
content VARCHAR(255) NOT NULL
)
class UnitOfWork
{
private $connection;
private $identityMap;
private $data;
public function __construct(\PDO $connection)
{
$this->connection = $connection;
$this->identityMap = [];
$this->data = [];
}
public function find(int $id): Tweet
{
if (isset($this->identityMap[$id])) {
return $this->identityMap[$id];
}
$query = $this->connection->prepare('SELECT * FROM tweets WHERE id = ?');
$query->execute([ $id ]);
if (false === $data = $query->fetch()) {
throw new \Exception(\sprintf('Tweet with id "%d" not found.', $id));
}
$id = (int) $data['id'];
// Исходные данные сохраняются для того, чтобы в дальнейшем вычислить изменения.
$this->data[$id] = $data;
$tweet = new Tweet($id, $data['content']);
$this->identityMap[$id] = $tweet;
return $tweet;
}
public function commit(): void
{
// Вообще говоря, лучше вычислить все изиенения, создать один "большой" запрос
// и выполнить его внутри транзакции, но для простоты мы сделаем для каждого
// изменения отдельный запрос
$query = $this->connection->prepare('UPDATE tweets SET content = ? WHERE id = ?');
foreach ($this->identityMap as $tweet) {
if ($tweet->getContent() !== $this->data[$tweet->getId()]['content']) {
$query->execute([ $tweet->getContent(), $tweet->getId() ]);
}
}
}
}
commit()
который отвечает за вычисление изменений в сохранённых в UoW объектах и синхронизацию этих изменений с хранилищем (базой данных).commit()
паттерна Unit of Work для вычисления разницы между исходными данными и накопленными изменениями. A blob: URL does not refer to data the exists on the server, it refers to data that your browser currently has in memory, for the current page. It will not be available on other pages, it will not be available in other browsers, and it will not be available from other computers