Merge pull request 'develop' (#2) from develop into master

Reviewed-on: #2
This commit is contained in:
2025-09-29 16:44:45 -03:00
66 changed files with 841 additions and 360 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@
# PHPStorm
**/.idea/
# PHPUnit
**/.phpunit.cache/

View File

@ -28,16 +28,16 @@
## Setup
```
$container->set(ProVM\Concept\Database\Query\Select::class, function(Psr\Container\ContainerInterface $container) {
$container->set(Database\Define\Query\Select::class, function(Psr\Container\ContainerInterface $container) {
return $container->get(ProVM\Database\Query\MySQL\Select::class);
});
$container->set(ProVM\Concept\Database\Query\Insert::class, function(Psr\Container\ContainerInterface $container) {
$container->set(Database\Define\Query\Insert::class, function(Psr\Container\ContainerInterface $container) {
return $container->get(ProVM\Database\Query\MySQL\Insert::class);
});
$container->set(ProVM\Concept\Database\Query\Update::class, function(Psr\Container\ContainerInterface $container) {
$container->set(Database\Define\Query\Update::class, function(Psr\Container\ContainerInterface $container) {
return $container->get(ProVM\Database\Query\MySQL\Update::class);
});
$container->set(ProVM\Concept\Database\Query\Delete::class, function(Psr\Container\ContainerInterface $container) {
$container->set(Database\Define\Query\Delete::class, function(Psr\Container\ContainerInterface $container) {
return $container->get(ProVM\Database\Query\MySQL\Delete::class);
});
```

View File

@ -1,9 +1,9 @@
{
"name": "provm/query_builder",
"version": "3.0.0",
"type": "project",
"require-dev": {
"phpunit/phpunit": "^9.5",
"kint-php/kint": "^4.2"
"phpunit/phpunit": "^10"
},
"authors": [
{
@ -15,7 +15,7 @@
},
"autoload": {
"psr-4": {
"ProVM\\": "src/"
"Database\\": "src/"
}
}
}

25
phpunit.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheDirectory=".phpunit.cache"
executionOrder="depends,defects"
requireCoverageMetadata="false"
beStrictAboutCoverageMetadata="false"
beStrictAboutOutputDuringTests="true"
displayDetailsOnPhpunitDeprecations="true"
failOnPhpunitDeprecation="true"
failOnRisky="true"
failOnWarning="true">
<testsuites>
<testsuite name="default">
<directory>tests</directory>
</testsuite>
</testsuites>
<source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true">
<include>
<directory>src</directory>
</include>
</source>
</phpunit>

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Concept\Database;
interface Query
{
public function build(): string;
public function __toString(): string;
}

View File

@ -1,10 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Create extends Query
{
public function table(string $table): Create;
public function columns(array|string $columns): Create;
}

View File

@ -1,10 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Delete extends Query
{
public function from(string $table): Delete;
public function where(array|string $conditions): Delete;
}

View File

@ -1,9 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Drop extends Query
{
public function table(string $table): Drop;
}

View File

@ -1,12 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Insert extends Query
{
public function into(string $table): Insert;
public function columns(array|string $columns): Insert;
public function values(array|string $values): Insert;
public function select(Select|string $select): Insert;
}

View File

@ -1,15 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Select extends Query
{
public function columns(array|string $columns = '*'): Select;
public function from(string $table): Select;
public function joined(array|string $joins): Select;
public function where(array|string $conditions): Select;
public function groupBy(array|string $grouping): Select;
public function having(array|string $having): Select;
public function orderBy(array|string $ordering): Select;
}

View File

@ -1,9 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Truncate extends Query
{
public function table(string $table): Truncate;
}

View File

@ -1,11 +0,0 @@
<?php
namespace ProVM\Concept\Database\Query;
use ProVM\Concept\Database\Query;
interface Update extends Query
{
public function table(string $table): Update;
public function set(array|string $value_pairs): Update;
public function where(array|string $conditions): Update;
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Create extends Query\Create
{
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Delete extends Query\Delete
{
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Drop extends Query\Drop
{
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Insert extends Query\Insert
{
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Truncate extends Query\Truncate
{
}

View File

@ -1,8 +0,0 @@
<?php
namespace ProVM\Database\Query\MySQL;
use ProVM\Implement\Database\Query;
class Update extends Query\Update
{
}

9
src/Define/Query.php Normal file
View File

@ -0,0 +1,9 @@
<?php
namespace Database\Define;
use Stringable;
interface Query extends Stringable
{
public function build(): string;
}

View File

@ -1,5 +1,5 @@
<?php
namespace ProVM\Concept\Database\Query;
namespace Database\Define\Query;
interface Builder
{

View File

@ -0,0 +1,11 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Create extends Query
{
public function table(string $table): self;
public function columns(array|string $columns): self;
public function foreign(array|string $columnDefinition): self;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Delete extends Query
{
public function from(string $table): self;
public function where(array|string $conditions): self;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Drop extends Query
{
public function table(string $table): self;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Insert extends Query
{
public function into(string $table): self;
public function columns(array|string $columns): self;
public function values(array|string $values): self;
public function select(Select|string $select): self;
}

View File

@ -0,0 +1,15 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Select extends Query
{
public function columns(array|string $columns = '*'): self;
public function from(string $table): self;
public function joined(array|string $joins): self;
public function where(array|string $conditions): self;
public function groupBy(array|string $grouping): self;
public function having(array|string $having): self;
public function orderBy(array|string $ordering): self;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Truncate extends Query
{
public function table(string $table): self;
}

View File

@ -0,0 +1,11 @@
<?php
namespace Database\Define\Query;
use Database\Define\Query;
interface Update extends Query
{
public function table(string $table): self;
public function set(array|string $value_pairs): self;
public function where(array|string $conditions): self;
}

View File

@ -0,0 +1,15 @@
<?php
namespace Database\Except\Missing;
use Throwable;
use Database\Except;
class Columns extends Except\Query
{
public function __construct(string $tableName, ?Throwable $previous = null)
{
$message = "Missing columns for {$tableName}";
$code = 1;
parent::__construct($message, $code, $previous);
}
}

15
src/Except/Query.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace Database\Except;
use Throwable;
use Exception;
abstract class Query extends Exception
{
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null)
{
$message = "Query Exception: {$message}";
$code = 1100 + $code;
parent::__construct($message, $code, $previous);
}
}

17
src/Ideal/Query.php Normal file
View File

@ -0,0 +1,17 @@
<?php
namespace Database\Ideal;
use Database\Define;
abstract class Query implements Define\Query
{
public function getType(): string
{
$class = explode("\\", get_class($this));
return array_pop($class);
}
public function __toString(): string
{
return $this->build();
}
}

139
src/Ideal/Query/Create.php Normal file
View File

@ -0,0 +1,139 @@
<?php
namespace Database\Ideal\Query;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\hasTable;
use Database\Except;
abstract class Create extends Query implements Define\Query\Create
{
use hasTable;
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->table($table);
}
}
public function isTemp(): self
{
$this->temp = true;
return $this;
}
public function ifNotExists(): self
{
$this->exists = true;
return $this;
}
public function table(string $table): self
{
return $this->setTable($table);
}
public function columns(array|string $columns): self
{
return $this->setColumns($columns);
}
public function foreign(array|string $columnDefinition): self
{
return $this->setForeign($columnDefinition);
}
protected bool $temp = false;
protected bool $exists = false;
protected array|string $columns;
protected array|string $foreign;
public function getColumns(): array
{
if (!isset($this->columns)) {
throw new Except\Missing\Columns($this->getTable());
}
return $this->columns;
}
public function addColumn(string $column): self
{
$this->columns []= $column;
return $this;
}
public function setColumns(array|string $columns): self
{
if (is_string($columns)) {
$this->addColumn($columns);
return $this;
}
foreach ($columns as $column) {
$this->addColumn($column);
}
return $this;
}
public function getForegin(): array
{
return $this->foreign;
}
public function addForeign(string|array $definition): self
{
if (is_string($definition)) {
$this->foreign []= $definition;
return $this;
}
$ids = implode(', ', $definition['ids']);
$columns = $definition['columns'];
if (is_array($definition['columns'])) {
$columns = implode(', ', $definition['columns']);
}
$delete = $definition['delete'] ?? 'CASCADE';
$update = $definition['update'] ?? 'CASCADE';
$fk = implode('_', ['fk', str_replace('.', '_', $definition['table']), $ids]);
$this->foreign []= "CONSTRAINT {$fk} FOREIGN KEY ({$columns}) REFERENCES {$definition['table']} ({$ids}) ON DELETE {$delete} ON UPDATE {$update}";
return $this;
}
public function setForeign(array|string $columnDefinition): self
{
if (is_string($columnDefinition)) {
$this->addForeign($columnDefinition);
return $this;
}
foreach ($columnDefinition as $column) {
$this->addForeign($column);
}
return $this;
}
protected function getTempString(): string
{
return ($this->temp) ? ' TEMPORARY' : '';
}
protected function getIfNotExistsString(): string
{
return ($this->exists) ? ' IF NOT EXISTS' : '';
}
protected function getColumnsString(): string
{
if (!isset($this->columns)) {
throw new Except\Missing\Columns($this->getTable());
}
if (is_string($this->columns)) {
return $this->columns;
}
return implode(', ', $this->getColumns());
}
protected function getForeignString(): string
{
if (!isset($this->foreign)) {
return '';
}
if (is_string($this->foreign)) {
return ", {$this->foreign}";
}
return ', ' . implode(', ', $this->getForegin());
}
public function build(): string
{
return "CREATE{$this->getTempString()} TABLE{$this->getIfNotExistsString()} {$this->getTable()} ({$this->getColumnsString()}{$this->getForeignString()})";
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Database\Ideal\Query;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\{hasConditions, hasTable};
abstract class Delete extends Query implements Define\Query\Delete
{
use hasTable, hasConditions;
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->from($table);
}
}
public function from(string $table): self
{
return $this->setTable($table);
}
public function where(array|string $conditions): self
{
return $this->setConditions($conditions);
}
public function build(): string
{
return implode('', [
"DELETE FROM {$this->getTable()}",
$this->getConditionsString()
]);
}
}

37
src/Ideal/Query/Drop.php Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace Database\Ideal\Query;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\hasTable;
abstract class Drop extends Query implements Define\Query\Drop
{
use hasTable;
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->table($table);
}
}
public function table(string $table): self
{
return $this->setTable($table);
}
public function cascade(): self
{
$this->cascade = true;
return $this;
}
protected bool $cascade = false;
protected function getCascadeString(): string
{
return $this->cascade ? ' CASCADE' : '';
}
public function build(): string
{
return "DROP TABLE {$this->getTable()}{$this->getCascadeString()}";
}
}

View File

@ -1,33 +1,41 @@
<?php
namespace ProVM\Implement\Database\Query;
namespace Database\Ideal\Query;
use ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\hasTable;
abstract class Insert extends Query implements Database\Query\Insert
abstract class Insert extends Query implements Define\Query\Insert
{
use hasTable;
public function into(string $table): Database\Query\Insert
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->into($table);
}
}
public function into(string $table): self
{
return $this->setTable($table);
}
public function columns(array|string $columns): Database\Query\Insert
public function columns(array|string $columns): self
{
return $this->setColumns($columns);
}
public function values(array|string $values): Database\Query\Insert
public function values(array|string $values): self
{
return $this->setValues($values);
}
public function select(Database\Query\Select|string $select): Database\Query\Insert
public function select(Define\Query\Select|string $select): self
{
return $this->setSelect($select);
}
protected array|string $columns;
protected array|string $values;
protected Database\Query\Select|string $select;
protected Define\Query\Select|string $select;
public function getColumns(): array|string
{
@ -37,22 +45,22 @@ abstract class Insert extends Query implements Database\Query\Insert
{
return $this->values;
}
public function getSelect(): Database\Query\Select|string
public function getSelect(): Define\Query\Select|string
{
return $this->select;
}
public function setColumns(array|string $columns): Database\Query\Insert
public function setColumns(array|string $columns): self
{
$this->columns = $columns;
return $this;
}
public function setValues(array|string $values): Database\Query\Insert
public function setValues(array|string $values): self
{
$this->values = $values;
return $this;
}
public function setSelect(Database\Query\Select|string $select): Database\Query\Insert
public function setSelect(Define\Query\Select|string $select): self
{
$this->select = $select;
return $this;

View File

@ -1,10 +1,11 @@
<?php
namespace ProVM\Implement\Database\Query;
namespace Database\Ideal\Query;
use ProVM\Concept\Database;
use ProVM\Implement\Database\Query;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\{hasConditions, hasTable};
abstract class Select extends Query implements Database\Query\Select
abstract class Select extends Query implements Define\Query\Select
{
use hasTable, hasConditions;
@ -13,40 +14,55 @@ abstract class Select extends Query implements Database\Query\Select
$this->columns($columns);
}
public function columns(array|string $columns = '*'): Database\Query\Select
public function columns(array|string $columns = '*'): self
{
return $this->setColumns($columns);
}
public function from(string $table): Database\Query\Select
public function from(string $table): self
{
return $this->setTable($table);
}
public function joined(array|string $joins): Database\Query\Select
public function joined(array|string $joins): self
{
return $this->setJoins($joins);
}
public function where(array|string $conditions): Database\Query\Select
public function where(array|string $conditions): self
{
return $this->setConditions($conditions);
}
public function groupBy(array|string $grouping): Database\Query\Select
public function groupBy(array|string $grouping): self
{
return $this->setGroups($grouping);
}
public function having(array|string $having): Database\Query\Select
public function having(array|string $having): self
{
return $this->setHaving($having);
}
public function orderBy(array|string $ordering): Database\Query\Select
public function orderBy(array|string $ordering): self
{
return $this->setOrders($ordering);
}
public function limit(int $limit, ?int $offset = null): self
{
$this->limit = $limit;
if ($offset !== null) {
$this->offset($offset);
}
return $this;
}
public function offset(int $offset): self
{
$this->offset = $offset;
return $this;
}
protected array|string $columns;
protected array|string $joins;
protected array|string $groups;
protected array|string $having;
protected array|string $orders;
protected int $limit;
protected int $offset;
public function getColumns(): array|string
{
@ -69,7 +85,7 @@ abstract class Select extends Query implements Database\Query\Select
return $this->orders;
}
public function addColumn(string $column, ?string $alias = null): Database\Query\Select
public function addColumn(string $column, ?string $alias = null): self
{
if ($column === '*') {
$this->columns []= $column;
@ -82,22 +98,22 @@ abstract class Select extends Query implements Database\Query\Select
$this->columns[] = "`{$column}`{$a}";
return $this;
}
public function addJoin(string $table, string $expression): Database\Query\Select
public function addJoin(string $table, string $expression): self
{
$this->joins []= "{$table} ON {$expression}";
return $this;
}
public function addGroup(string $group): Database\Query\Select
public function addGroup(string $group): self
{
$this->groups []= "`{$group}`";
return $this;
}
public function addHaving(string $having): Database\Query\Select
public function addHaving(string $having): self
{
$this->having []= $having;
return $this;
}
public function addOrder(string $column, ?string $direction = null): Database\Query\Select
public function addOrder(string $column, ?string $direction = null): self
{
if ($direction === null) {
$direction = 'ASC';
@ -106,7 +122,7 @@ abstract class Select extends Query implements Database\Query\Select
return $this;
}
public function setColumns(array|string $columns): Database\Query\Select
public function setColumns(array|string $columns): self
{
if (is_string($columns)) {
$this->columns = $columns;
@ -123,7 +139,7 @@ abstract class Select extends Query implements Database\Query\Select
}
return $this;
}
public function setJoins(array|string $joins): Database\Query\Select
public function setJoins(array|string $joins): self
{
if (is_string($joins)) {
$this->joins = $joins;
@ -136,7 +152,7 @@ abstract class Select extends Query implements Database\Query\Select
}
return $this;
}
public function setGroups(array|string $groups): Database\Query\Select
public function setGroups(array|string $groups): self
{
if (is_string($groups)) {
$this->groups = $groups;
@ -147,7 +163,7 @@ abstract class Select extends Query implements Database\Query\Select
}
return $this;
}
public function setHaving(array|string $having): Database\Query\Select
public function setHaving(array|string $having): self
{
if (is_string($having)) {
$this->having = $having;
@ -158,7 +174,7 @@ abstract class Select extends Query implements Database\Query\Select
}
return $this;
}
public function setOrders(array|string $orders): Database\Query\Select
public function setOrders(array|string $orders): self
{
if (is_string($orders)) {
$this->orders = $orders;
@ -178,8 +194,12 @@ abstract class Select extends Query implements Database\Query\Select
protected function getColumnsString(): string
{
if (!isset($this->columns) or (is_array($this->getColumns()) and count($this->getColumns()) === 0)
or (is_string($this->getColumns()) and $this->getColumns() === '*')) {
return '*';
}
$columns = (is_array($this->getColumns())) ? implode(', ', $this->getColumns()) : $this->getColumns();
return " ({$columns})";
return "{$columns}";
}
protected function getJoinsString(): string
{
@ -244,6 +264,17 @@ abstract class Select extends Query implements Database\Query\Select
$ordering = (is_array($this->getOrders())) ? implode(', ', $this->getOrders()) : $this->getOrders();
return " ORDER BY {$ordering}";
}
protected function getLimitString(): string
{
if (!isset($this->limit)) {
return '';
}
$limit = " LIMIT {$this->limit}";
if (isset($this->offset)) {
$limit .= " OFFSET {$this->offset}";
}
return $limit;
}
public function build(): string
{
@ -254,7 +285,8 @@ abstract class Select extends Query implements Database\Query\Select
$this->getConditionsString(),
$this->getGroupsString(),
$this->getHavingString(),
$this->getOrderString()
$this->getOrderString(),
$this->getLimitString()
]);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Database\Ideal\Query;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\hasTable;
abstract class Truncate extends Query implements Define\Query\Truncate
{
use hasTable;
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->table($table);
}
}
public function table(string $table): self
{
return $this->setTable($table);
}
public function build(): string
{
return "TRUNCATE TABLE {$this->getTable()}";
}
}

View File

@ -1,22 +1,29 @@
<?php
namespace ProVM\Implement\Database\Query;
namespace Database\Ideal\Query;
use ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
use Database\Ideal\Query;
use Database\Define;
use Database\Reinforce\Query\{hasConditions, hasTable};
abstract class Update extends Query implements Database\Query\Update
abstract class Update extends Query implements Define\Query\Update
{
use hasTable, hasConditions;
public function table(string $table): Database\Query\Update
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->table($table);
}
}
public function table(string $table): self
{
return $this->setTable($table);
}
public function set(array|string $value_pairs): Database\Query\Update
public function set(array|string $value_pairs): self
{
return $this->setValues($value_pairs);
}
public function where(array|string $conditions): Database\Query\Update
public function where(array|string $conditions): self
{
return $this->setConditions($conditions);
}
@ -28,8 +35,14 @@ abstract class Update extends Query implements Database\Query\Update
return $this->values;
}
public function addValue(string $column, int|string $value): Database\Query\Update
public function addValue(string|array $values): self
{
if (is_string($values)) {
$this->values []= $values;
return $this;
}
$column = $values['column'] ?? $values[0];
$value = $values['value'] ?? $values[1];
if (!is_numeric($value)) {
$value = "'{$value}'";
}
@ -37,16 +50,14 @@ abstract class Update extends Query implements Database\Query\Update
return $this;
}
public function setValues(array|string $values): Database\Query\Update
public function setValues(array|string $values): self
{
if (is_string($values)) {
$this->values = $values;
$this->addValue($values);
return $this;
}
foreach ($values as $value) {
$column = $value['column'] ?? $value[0];
$val = $value['value'] ?? $value[1];
$this->addValue($column, $val);
$this->addValue($value);
}
return $this;
}

View File

@ -1,12 +0,0 @@
<?php
namespace ProVM\Implement\Database;
use ProVM\Concept\Database;
abstract class Query implements Database\Query
{
public function __toString(): string
{
return $this->build();
}
}

View File

@ -1,62 +0,0 @@
<?php
namespace ProVM\Implement\Database\Query;
use ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
abstract class Create extends Query implements Database\Query\Create
{
use hasTable;
public function __construct(string $table)
{
$this->table($table);
}
public function table(string $table): Database\Query\Create
{
return $this->setTable($table);
}
public function columns(array|string $columns): Database\Query\Create
{
return $this->setColumns($columns);
}
protected array|string $columns;
public function getColumns(): array
{
return $this->columns;
}
public function addColumn(string $column): Database\Query\Create
{
$this->columns []= $column;
return $this;
}
public function setColumns(array|string $columns): Database\Query\Create
{
if (is_string($columns)) {
$this->columns = $columns;
return $this;
}
foreach ($columns as $column) {
$this->addColumn($column);
}
return $this;
}
protected function getColumnsString(): string
{
if (is_string($this->columns)) {
return $this->columns;
}
return implode(', ', $this->getColumns());
}
public function build(): string
{
return "CREATE {$this->getTable()} ({$this->getColumnsString()})";
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
use ProVM\Implement\Database\Query;
abstract class Delete extends Query implements Database\Query\Delete
{
use hasTable, hasConditions;
public function from(string $table): Database\Query\Delete
{
return $this->setTable($table);
}
public function where(array|string $conditions): Database\Query\Delete
{
return $this->setConditions($conditions);
}
public function build(): string
{
return implode('', [
"DELETE FROM {$this->getTable()}",
$this->getConditionsString()
]);
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace ProVM\Implement\Database\Query;
use ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
abstract class Drop extends Query implements Database\Query\Drop
{
use hasTable;
public function __construct(?string $table = null)
{
if ($table !== null) {
$this->table($table);
}
}
public function table(string $table): Database\Query\Drop
{
return $this->setTable($table);
}
public function build(): string
{
return "DROP TABLE {$this->getTable()}";
}
}

View File

@ -1,24 +0,0 @@
<?php
namespace ProVM\Implement\Database\Query;
use ProVM\Implement\Database\Query;
use ProVM\Concept\Database;
abstract class Truncate extends Query implements Database\Query\Truncate
{
use hasTable;
public function __construct(string $table)
{
$this->table($table);
}
public function table(string $table): Database\Query\Truncate
{
return $this->setTable($table);
}
public function build(): string
{
return "TRUNCATE TABLE {$this->getTable()}";
}
}

View File

@ -1,7 +1,9 @@
<?php
namespace ProVM\Database\Query;
namespace Database\Implement\Query;
use ProVM\Concept\Database\Query;
use Exception;
use FilesystemIterator;
use Database\Define\Query;
class Builder implements Query\Builder
{
@ -10,6 +12,34 @@ class Builder implements Query\Builder
$this->setQueries($query_classes);
}
/**
* @throws Exception
*/
public static function getClasses(string $databaseType): array
{
$directories = new FilesystemIterator(__DIR__);
foreach ($directories as $directory) {
if (!$directory->isDir()) {
continue;
}
if (strtolower($directory->getBasename()) !== strtolower($databaseType)) {
continue;
}
$classes = [];
$files = new FilesystemIterator($directory->getPathname());
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
$base = $file->getBasename('.php');
$interface = "ProVM\\Concept\\Database\\Query\\{$base}";
$class = __NAMESPACE__ . "\\{$directory->getBasename()}\\{$base}";
$classes[$interface] = $class;
}
return $classes;
}
throw new Exception("Database type's classes not found");
}
protected array $query_classes;
protected function getQueries(): array
@ -22,13 +52,13 @@ class Builder implements Query\Builder
return $this->query_classes[$query_interface];
}
protected function addQuery(string $query_interface, string $query): Builder
protected function addQuery(string $query_interface, string $query): self
{
$this->query_classes[$query_interface] = $query;
return $this;
}
protected function setQueries(array $queries): Builder
protected function setQueries(array $queries): self
{
foreach ($queries as $interface => $query) {
$this->addQuery($interface, $query);

View File

@ -0,0 +1,13 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Create extends Query\Create
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Delete extends Query\Delete
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Drop extends Query\Drop
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Insert extends Query\Insert
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
}

View File

@ -1,11 +1,11 @@
<?php
namespace ProVM\Database\Query\MySQL;
namespace Database\Implement\Query\MySQL;
use ProVM\Implement\Database\Query;
use Database\Ideal\Query;
class Select extends Query\Select
{
public function limit(int $limit, ?int $offset = null): Select
public function limit(int $limit, ?int $offset = null): self
{
$this->setLimit($limit);
if ($offset !== null) {
@ -14,6 +14,12 @@ class Select extends Query\Select
return $this;
}
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
protected int $limit;
protected int $offset;
@ -26,12 +32,12 @@ class Select extends Query\Select
return $this->offset;
}
public function setLimit(int $limit): Select
public function setLimit(int $limit): self
{
$this->limit = $limit;
return $this;
}
public function setOffset(int $offset): Select
public function setOffset(int $offset): self
{
$this->offset = $offset;
return $this;
@ -48,10 +54,11 @@ class Select extends Query\Select
public function build(): string
{
$query = [
return parent::build();
/*$query = [
parent::build(),
$this->getLimitString()
];
return implode('', $query);
return implode('', $query);*/
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Truncate extends Query\Truncate
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Database\Implement\Query\MySQL;
use Database\Ideal\Query;
class Update extends Query\Update
{
public function getTable(): string
{
$table = parent::getTable();
return "`{$table}`";
}
public function build(): string
{
return implode('', [
"UPDATE TABLE {$this->getTable()}",
$this->getValuesString(),
$this->getConditionsString()
]);
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Create extends Query\Create
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Delete extends Query\Delete
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Drop extends Query\Drop
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Insert extends Query\Insert
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Select extends Query\Select
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Truncate extends Query\Truncate
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Database\Implement\Query\PostgreSQL;
use Database\Ideal\Query;
class Update extends Query\Update
{
}

View File

@ -1,5 +1,5 @@
<?php
namespace ProVM\Implement\Database\Query;
namespace Database\Reinforce\Query;
trait hasConditions
{
@ -10,9 +10,20 @@ trait hasConditions
return $this->conditions ?? '';
}
protected function setConditions(array|string $conditions)
protected function setConditions(array|string $conditions): self
{
$this->conditions = $conditions;
if (is_array($conditions)) {
foreach ($conditions as $condition) {
$this->addCondition($condition);
}
} else {
$this->addCondition($conditions);
}
return $this;
}
protected function addCondition(array|string $condition): self
{
$this->conditions []= $condition;
return $this;
}
@ -35,7 +46,8 @@ trait hasConditions
return "AND {$condition}";
}, $conditions));
}
if (trim($conditions) === '') {
$conditions = trim($conditions);
if ($conditions === '') {
return '';
}
return " WHERE {$conditions}";

View File

@ -1,5 +1,5 @@
<?php
namespace ProVM\Implement\Database\Query;
namespace Database\Reinforce\Query;
trait hasTable
{
@ -10,9 +10,8 @@ trait hasTable
return $this->table;
}
public function setTable(string $table, ?string $alias = null)
public function setTable(string $table, ?string $alias = null): self
{
$table = "`{$table}`";
if ($alias !== null) {
$table = "{$table} '{$alias}'";
}

24
tests/MySQLCreateTest.php Normal file
View File

@ -0,0 +1,24 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLCreateTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Create();
$query->table('test_table');
$query->columns('`column1` int');
$expected = "CREATE TABLE `test_table` (`column1` int)";
$this->assertEquals($expected, "{$query}");
}
public function testMissingColumns(): void
{
$query = new Database\Implement\Query\MySQL\Create();
$query->table('test_table');
$this->expectException(Database\Except\Missing\Columns::class);
echo "{$query}";
}
}

15
tests/MySQLDeleteTest.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLDeleteTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Delete();
$query->from('test_table');
$expected = "DELETE FROM `test_table`";
$this->assertEquals($expected, "{$query}");
}
}

15
tests/MySQLDropTest.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLDropTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Drop();
$query->table('test_table');
$expected = "DROP TABLE `test_table`";
$this->assertEquals($expected, "{$query}");
}
}

16
tests/MySQLInsertTest.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLInsertTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Insert();
$query->into('test_table');
$query->values('?, ?, ?');
$expected = "INSERT INTO `test_table` VALUES (?, ?, ?)";
$this->assertEquals($expected, "{$query}");
}
}

24
tests/MySQLSelectTest.php Normal file
View File

@ -0,0 +1,24 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLSelectTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Select();
$query->from('test_table');
$expected = "SELECT * FROM `test_table`";
$this->assertEquals($expected, "{$query}");
}
public function testColumns(): void
{
$query = new Database\Implement\Query\MySQL\Select('asd');
$query->from('test_table');
$expected = "SELECT asd FROM `test_table`";
$this->assertEquals($expected, "{$query}");
}
}

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLTruncateTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Truncate();
$query->table('test_table');
$expected = "TRUNCATE TABLE `test_table`";
$this->assertEquals($expected, "{$query}");
}
}

16
tests/MySQLUpdateTest.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\TestCase;
class MySQLUpdateTest extends TestCase
{
public function testBaseQuery(): void
{
$query = new Database\Implement\Query\MySQL\Update();
$query->table('test_table');
$query->set('column1 = 0');
$expected = "UPDATE TABLE `test_table` SET column1 = 0";
$this->assertEquals($expected, "{$query}");
}
}