move query execution logic to a reusable place, implement insertion of entities
parent
c0dd69eac0
commit
21a93966d7
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Repository\ResolutionStrategy\Execution;
|
||||||
|
|
||||||
|
use Kartierung\Analyze\Result\EntityField;
|
||||||
|
use Kartierung\Analyze\Result\EntityResult;
|
||||||
|
use Kartierung\Repository\InvalidCall;
|
||||||
|
use PDO;
|
||||||
|
|
||||||
|
readonly class InsertEntity
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private PDO $pdo
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param EntityResult<object> $entityResult
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function insert(EntityResult $entityResult, array $data): object
|
||||||
|
{
|
||||||
|
$newId = $this->insertWithNewId($entityResult, $data);
|
||||||
|
|
||||||
|
if ($newId === false) {
|
||||||
|
throw new InvalidCall(
|
||||||
|
"Expected new ID to be generated by database. "
|
||||||
|
. "New entities must be provided with a new ID by the database schema."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newEntity = (new SelectEntityById($this->pdo))->select($entityResult, $newId);
|
||||||
|
if (!$newEntity) {
|
||||||
|
throw new InvalidCall(
|
||||||
|
"No Entity with id $newId could be found in table $entityResult->tableName after insert."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function insertWithNewId(EntityResult $entityResult, array $data): string|false
|
||||||
|
{
|
||||||
|
$cols = implode(", ", array_map(
|
||||||
|
static fn(EntityField $field) => $field->columnName,
|
||||||
|
$entityResult->fields
|
||||||
|
));
|
||||||
|
$vals = implode(", ", array_map(
|
||||||
|
static fn($_) => "?",
|
||||||
|
$entityResult->fields
|
||||||
|
));
|
||||||
|
$params = array_map(
|
||||||
|
static fn(EntityField $field) => $data[$field->columnName] ?? null,
|
||||||
|
$entityResult->fields
|
||||||
|
);
|
||||||
|
|
||||||
|
$sql = "INSERT INTO $entityResult->tableName ($cols) VALUES ($vals)";
|
||||||
|
$prepStmt = $this->pdo->prepare($sql);
|
||||||
|
$prepStmt->execute($params);
|
||||||
|
|
||||||
|
return $this->pdo->lastInsertId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Repository\ResolutionStrategy\Execution;
|
||||||
|
|
||||||
|
use Kartierung\Analyze\Result\EntityField;
|
||||||
|
use Kartierung\Analyze\Result\EntityResult;
|
||||||
|
use Kartierung\Sql\DataToEntityMapper;
|
||||||
|
use PDO;
|
||||||
|
use PDOStatement;
|
||||||
|
|
||||||
|
readonly class SelectAllEntities
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private PDO $pdo
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template E of object
|
||||||
|
* @param EntityResult<E> $entityResult
|
||||||
|
* @return list<E>
|
||||||
|
*/
|
||||||
|
public function selectAll(EntityResult $entityResult): array
|
||||||
|
{
|
||||||
|
$fields = implode(
|
||||||
|
', ',
|
||||||
|
array_map(
|
||||||
|
static fn(EntityField $e) => $e->columnName, $entityResult->fields
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$sql = "
|
||||||
|
SELECT $fields
|
||||||
|
FROM {$entityResult->tableName}
|
||||||
|
";
|
||||||
|
|
||||||
|
/** @var PDOStatement $stmt */
|
||||||
|
$stmt = $this->pdo->prepare($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$statementResult = [];
|
||||||
|
|
||||||
|
$mapper = new DataToEntityMapper($entityResult);
|
||||||
|
while ($row = $stmt->fetch(
|
||||||
|
mode: PDO::FETCH_ASSOC
|
||||||
|
)) {
|
||||||
|
/** @var array<string, mixed> $row */
|
||||||
|
$entity = $mapper->toEntity($row);
|
||||||
|
$statementResult[] = $entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $statementResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Repository\ResolutionStrategy\Execution;
|
||||||
|
|
||||||
|
use Kartierung\Analyze\Result\EntityField;
|
||||||
|
use Kartierung\Analyze\Result\EntityResult;
|
||||||
|
use Kartierung\Sql\DataToEntityMapper;
|
||||||
|
use PDO;
|
||||||
|
use PDOStatement;
|
||||||
|
|
||||||
|
readonly class SelectEntityById
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private PDO $pdo
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template E of object
|
||||||
|
* @param EntityResult<E> $entityResult
|
||||||
|
* @param mixed $id
|
||||||
|
* @return E|null
|
||||||
|
*/
|
||||||
|
public function select(EntityResult $entityResult, mixed $id): ?object
|
||||||
|
{
|
||||||
|
$fields = implode(
|
||||||
|
', ',
|
||||||
|
array_map(
|
||||||
|
static fn(EntityField $e) => $e->columnName, $entityResult->fields
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$idField = $entityResult->idField->name;
|
||||||
|
|
||||||
|
$sql = "
|
||||||
|
SELECT $fields
|
||||||
|
FROM {$entityResult->tableName}
|
||||||
|
WHERE $idField = ?
|
||||||
|
";
|
||||||
|
|
||||||
|
/** @var PDOStatement $stmt */
|
||||||
|
$stmt = $this->pdo->prepare($sql);
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
|
||||||
|
/** @var array<string, mixed>|false $row */
|
||||||
|
$row = $stmt->fetch(mode: PDO::FETCH_ASSOC);
|
||||||
|
if ($row) {
|
||||||
|
$mapper = new DataToEntityMapper($entityResult);
|
||||||
|
return $mapper->toEntity($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Repository\ResolutionStrategy;
|
||||||
|
|
||||||
|
use Kartierung\Analyze\Result\ParameterFunction;
|
||||||
|
use Kartierung\Analyze\Result\RepositoryMethod;
|
||||||
|
use Kartierung\Analyze\Result\RepositoryMethodParameter;
|
||||||
|
use PHPUnit\Framework\Attributes\Group;
|
||||||
|
|
||||||
|
class SaveEntityTest extends SqliteBaseCase
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->getPdo()->exec(
|
||||||
|
"
|
||||||
|
CREATE TABLE SimpleEntity (
|
||||||
|
stringcol VARCHAR(250),
|
||||||
|
intcol INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
|
);
|
||||||
|
INSERT INTO SimpleEntity(stringcol, intcol)
|
||||||
|
VALUES ('dings', 1),
|
||||||
|
('bumms', 2);
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Group('integration')]
|
||||||
|
public function testSelectsData(): void
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
$strategy = new SaveEntity();
|
||||||
|
$method = new RepositoryMethod(
|
||||||
|
query: '',
|
||||||
|
returnType: '',
|
||||||
|
returnsNullable: true,
|
||||||
|
returnListType: '',
|
||||||
|
name: '',
|
||||||
|
parameters: [
|
||||||
|
new RepositoryMethodParameter(
|
||||||
|
name: '',
|
||||||
|
type: SimpleEntity::class,
|
||||||
|
function: ParameterFunction::STATEMENT_PARAMETER
|
||||||
|
)
|
||||||
|
],
|
||||||
|
resolutionStrategy: $strategy
|
||||||
|
);
|
||||||
|
$entity = new SimpleEntity(null, 'foobar');
|
||||||
|
$query = $method->createQuery([$entity]);
|
||||||
|
|
||||||
|
// When
|
||||||
|
$result = $query->execute($this->getPdo());
|
||||||
|
|
||||||
|
// Then
|
||||||
|
$this->assertInstanceOf(SimpleEntity::class, $result);
|
||||||
|
$this->assertNotNull($result->intcol);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue