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