setConnection($connection) ->setQueryBuilder($builder) ->setFactory($factory) ->setup(); } protected Connection $connection; public function setConnection(Connection $connection): Repository { $this->connection = $connection; return $this; } public function getConnection(): Connection { return $this->connection; } protected QueryBuilder $builder; public function setQueryBuilder(QueryBuilder $builder): RepositoryInterface { $this->builder = $builder; return $this; } public function getQueryBuilder(): QueryBuilder { return $this->builder; } protected Factory $factory; public function setFactory(Factory $factory): RepositoryInterface { $this->factory = $factory; return $this; } public function getFactory(): Factory { return $this->factory; } protected string $model; public function setModel(string $model_class): RepositoryInterface { $this->model = $model_class; return $this; } public function getModel(): string { return $this->model; } public function getNewModel(): Model { $class = $this->getModel(); return (new $class()) ->setRepository($this); } protected string $table; public function setTable(string $table): RepositoryInterface { $this->table = $table; return $this; } public function getTable(): string { return $this->table; } protected array $columns; public function setColumns(array $columns): RepositoryInterface { foreach ($columns as $column) { $this->addColumn($column); } return $this; } public function addColumn(string $column): RepositoryInterface { $this->columns []= $column; return $this; } public function getColumns(): array { return $this->columns; } protected array $required; public function setRequired(array $columns): RepositoryInterface { foreach ($columns as $item) { $this->addRequired($item); } return $this; } public function addRequired(string $column): RepositoryInterface { $this->required []= $column; return $this; } public function getRequired(): array { if (isset($this->optional) and !isset($this->required)) { return array_diff($this->getColumns(), $this->getOptional()); } return $this->required ?? $this->getColumns(); } protected array $optional; public function setOptional(array $columns): RepositoryInterface { foreach ($columns as $item) { $this->addColumn($item); } return $this; } public function addOptional(string $column): RepositoryInterface { $this->optional []= $column; return $this; } public function getOptional(): array { if (isset($this->required) and !isset($this->optional)) { return array_diff($this->getColumns(), $this->getRequired()); } return $this->optional ?? []; } public function fillData(Model $model, array $data): Model { foreach ($this->getRequired() as $column) { $m = 'set' . ucwords($column); $model->{$m}($data[$column]); } foreach ($this->getOptional() as $column) { if (isset($data[$column])) { $m = 'set' . ucwords($column); $model->{$m}($data[$column]); } } return $model; } public function load(array $data): Model { return $this->fillData($this->getNewModel() ->setId($data['id']), $data); } public function save(Model $model): void { if (!$model->isDirty() and !$model->isNew()) { return; } $cols = []; $values = []; foreach ($this->getColumns() as $column) { $m = 'get' . ucwords($column); $cols []= '?'; $values []= $model->{$m}(); } $query = $this->getQueryBuilder()->insert($this->getTable())->columns($this->getColumns())->values($cols); $this->getConnection()->execute($query, $values); } public function create(array $data): Model { return $this->fillData($this->getNewModel() ->setNew(), $data); } public function edit(Model $model, array $data): Model { foreach ($this->getColumns() as $col) { if (isset($data[$col])) { $m = 'set' . ucwords($col); $model->{$m}($data[$col]); } } return $model; } public function delete(Model $model): void { $query = $this->getQueryBuilder()->delete($this->getTable())->where(['id = ?']); $this->getConnection()->execute($query, [$model->getId()]); } public function fetchById(int $id): Model { $query = $this->getQueryBuilder() ->select() ->from($this->getTable()) ->where([['id', '?']]) ->limit(1); return $this->load($this->getConnection()->execute($query, [$id])->getAsArray()[0]); } public function fetchAll(): array { $query = $this->getQueryBuilder() ->select() ->from($this->getTable()); return array_map([$this, 'load'], $this->getConnection()->query($query)->getAsArray()); } }