table; } public function setTable(string $table): Repository { $this->table = $table; return $this; } public function load(array $data_row): Define\Model { $model = $this->create($data_row); $model->{$this->getKey()} = $data_row[$this->getKey()]; return $model; } public function remove(Define\Model $model): void { $query = $this->connection->getQueryBuilder() ->delete()->from($this->getTable()) ->where("{$this->getKey()} = ?"); $this->connection->execute($query, [$model->id]); } /** * @throws EmptyResult */ public function fetchById(int $id): Define\Model { $query = $this->connection->getQueryBuilder() ->select() ->from($this->getTable()) ->where("{$this->getKey()} = ?"); return $this->fetchOne($query, [$id]); } /** * @throws EmptyResult */ public function fetchAll(null|string|array $ordering = null): array { $query = $this->connection->getQueryBuilder() ->select() ->from($this->getTable()); if ($ordering !== null) { $query->order($ordering); } return $this->fetchMany($query); } protected function getKey(): string { return 'id'; } protected function parseData(Define\Model $model, ?array $data, Implement\Repository\MapperParser $data_map): Define\Model { if ($data === null) { return $model; } foreach ($data_map->getColumns() as $column) { if (!$data_map->hasMapper($column)) { $this->parsePlainColumn($model, $column, $data); continue; } $settings = $data_map->getMapper($column); if ($settings->parse($model, $column, $data)) { continue; } $property = $column; if ($settings->hasProperty()) { $property = $settings->property; } $this->setDefault($model, $property); } return $model; } protected function parsePlainColumn(Define\Model &$model, string $column, ?array $data): void { $property = $column; if (isset($data[$column])) { $model->{$property} = $data[$column]; return; } $this->setDefault($model, $property); } protected function setDefault(Define\Model &$model, string $property): void { $prop = new ReflectionProperty($model, $property); $type = $prop->getType()->getName(); $value = match ($type) { 'int' => 0, 'float' => 0.0, 'string' => '', default => null, }; $model->{$property} = $value; } protected function saveNew(array $columns, array $values): int { $query = $this->connection->getQueryBuilder() ->insert() ->into($this->getTable()) ->columns($columns) ->values(array_fill(0, count($columns), '?')); $this->connection->execute($query, $values); return $this->connection->getPDO()->lastInsertId(); } protected function update(Define\Model $model, array $columns, array $data): Define\Model { $changes = []; $values = []; foreach ($columns as $column) { if (in_array($column, array_keys($data))) { $changes []= $column; $values []= $data[$column]; } } if (count($changes) === 0) { return $model; } $columns_string = implode(', ', array_map(function($property) {return "`{$property}` = ?";}, $changes)); $query = $this->connection->getQueryBuilder() ->update($this->getTable()) ->set($columns_string) ->where("{$this->getKey()} = ?"); $values []= $model->{$this->getKey()}; $this->connection->execute($query, $values); return $this->fetchById($model->{$this->getKey()}); } protected function fetchOne(string $query, ?array $data = null): Define\Model { $result = $this->connection->execute($query, $data)->fetch(PDO::FETCH_ASSOC); if ($result === false) { throw new EmptyResult($query); } return $this->load($result); } protected function fetchMany(string $query, ?array $data = null): array { $results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC); if ($results === false) { throw new EmptyResult($query); } return array_map([$this, 'load'], $results); } protected function fetchAsArray(string $query, ?array $data = null): array { $results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC); if ($results === false) { throw new EmptyResult($query); } return $results; } public function filterData(array $data): array { return $data; } }