From 7e5da1effb5ea4c08d4c7578df10a56815351a0f Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 17:40:35 -0400 Subject: [PATCH 1/6] Ignore PHPStorm data --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7fba966..eed7ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ # Composer **/vendor/ **/*.lock + +# PHPStorm +**/.idea/ From 803e1a25d32d7129d2be7a56e3fcff9be5408de7 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 17:42:02 -0400 Subject: [PATCH 2/6] Dependencies --- composer.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a983212 --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name": "provm/query_builder", + "type": "project", + "require-dev": { + "phpunit/phpunit": "^9.5", + "kint-php/kint": "^4.2" + }, + "authors": [ + { + "name": "Aldarien", + "email": "aldarien85@gmail.com" + } + ], + "require": { + "psr/container": "^2.0" + }, + "autoload": { + "psr-4": { + "ProVM\\": "src/" + } + } +} From e83638e2230e5b3ebf4d945f96e9cfffa59466ec Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 17:40:03 -0400 Subject: [PATCH 3/6] Interfaces --- src/Concept/Database/Query.php | 8 ++++++++ src/Concept/Database/Query/Delete.php | 10 ++++++++++ src/Concept/Database/Query/Insert.php | 12 ++++++++++++ src/Concept/Database/Query/Select.php | 15 +++++++++++++++ src/Concept/Database/Query/Update.php | 11 +++++++++++ src/Concept/Database/QueryBuilder.php | 15 +++++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 src/Concept/Database/Query.php create mode 100644 src/Concept/Database/Query/Delete.php create mode 100644 src/Concept/Database/Query/Insert.php create mode 100644 src/Concept/Database/Query/Select.php create mode 100644 src/Concept/Database/Query/Update.php create mode 100644 src/Concept/Database/QueryBuilder.php diff --git a/src/Concept/Database/Query.php b/src/Concept/Database/Query.php new file mode 100644 index 0000000..6a325ee --- /dev/null +++ b/src/Concept/Database/Query.php @@ -0,0 +1,8 @@ + Date: Thu, 8 Sep 2022 17:40:51 -0400 Subject: [PATCH 4/6] Abstract implementations --- src/Alias/Database/Query.php | 12 ++ src/Alias/Database/Query/Delete.php | 59 ++++++++ src/Alias/Database/Query/Insert.php | 108 ++++++++++++++ src/Alias/Database/Query/Select.php | 222 ++++++++++++++++++++++++++++ src/Alias/Database/Query/Update.php | 91 ++++++++++++ 5 files changed, 492 insertions(+) create mode 100644 src/Alias/Database/Query.php create mode 100644 src/Alias/Database/Query/Delete.php create mode 100644 src/Alias/Database/Query/Insert.php create mode 100644 src/Alias/Database/Query/Select.php create mode 100644 src/Alias/Database/Query/Update.php diff --git a/src/Alias/Database/Query.php b/src/Alias/Database/Query.php new file mode 100644 index 0000000..0bda90d --- /dev/null +++ b/src/Alias/Database/Query.php @@ -0,0 +1,12 @@ +build(); + } +} diff --git a/src/Alias/Database/Query/Delete.php b/src/Alias/Database/Query/Delete.php new file mode 100644 index 0000000..a81d9c2 --- /dev/null +++ b/src/Alias/Database/Query/Delete.php @@ -0,0 +1,59 @@ +setTable($table); + } + public function where(array $conditions): DeleteInterface + { + return $this->setConditions($conditions); + } + + protected string $table; + public function setTable(string $table): DeleteInterface + { + $this->table = $table; + return $this; + } + public function getTable(): string + { + return $this->table; + } + protected array $conditions; + public function setConditions(array $conditions): DeleteInterface + { + foreach ($conditions as $condition) { + $this->addCondition($condition); + } + return $this; + } + public function addCondition(string $expression): DeleteInterface + { + $this->conditions []= $expression; + return $this; + } + public function getConditions(): array + { + return $this->conditions; + } + public function getConditionString(): string + { + return implode(' ', $this->getConditions()); + } + + public function build(): string + { + return implode(' ', [ + 'DELETE FROM', + $this->getTable(), + 'WHERE', + $this->getConditionString() + ]); + } +} diff --git a/src/Alias/Database/Query/Insert.php b/src/Alias/Database/Query/Insert.php new file mode 100644 index 0000000..4f633eb --- /dev/null +++ b/src/Alias/Database/Query/Insert.php @@ -0,0 +1,108 @@ +setTable($table); + } + public function columns(array $columns): InsertInterface + { + return $this->setColumns($columns); + } + public function values(array $values): InsertInterface + { + return $this->setValues($values); + } + public function select(Select $select): InsertInterface + { + return $this->setSelect($select); + } + + protected string $table; + public function setTable(string $table): InsertInterface + { + $this->table = $table; + return $this; + } + public function getTable(): string + { + return $this->table; + } + protected array $columns; + public function setColumns(array $columns): InsertInterface + { + foreach ($columns as $column) { + $this->addColumn($column); + } + return $this; + } + public function addColumn(string $column): InsertInterface + { + $this->columns []= $column; + return $this; + } + public function getColumns(): array + { + return $this->columns; + } + public function getColumnString(): string + { + return implode(', ', $this->getColumns()); + } + protected array $values; + public function setValues(array $values): InsertInterface + { + foreach ($values as $value) { + $this->addValue($value); + } + return $this; + } + public function addValue(int|string $value): InsertInterface + { + if (!is_numeric($value)) { + $value = "'{$value}'"; + } + $this->values []= $value; + return $this; + } + public function getValues(): array + { + return $this->values; + } + public function getValueString(): string + { + return implode(', ', $this->getValues()); + } + protected Select $select; + public function setSelect(Select $select): InsertInterface + { + $this->select = $select; + return $this; + } + public function getSelect(): Select + { + return $this->select; + } + + public function build(): string + { + $query = ["INSERT INTO"]; + $query []= $this->getTable(); + if (isset($this->columns)) { + $query []= "({$this->getColumnString()})"; + } + if (isset($this->select)) { + $query []= "{$this->getSelect()}"; + return implode(' ', $query); + } + $query []= 'VALUES'; + $query []= "({$this->getValueString()})"; + return implode(' ', $query); + } +} diff --git a/src/Alias/Database/Query/Select.php b/src/Alias/Database/Query/Select.php new file mode 100644 index 0000000..6b69c13 --- /dev/null +++ b/src/Alias/Database/Query/Select.php @@ -0,0 +1,222 @@ +setColumns($columns); + } + public function from(string $table): SelectInterface + { + return $this->setTable($table); + } + public function joins(array $joins): SelectInterface + { + return $this->setJoins($joins); + } + public function where(array $conditions): SelectInterface + { + return $this->setConditions($conditions); + } + public function groupBy(array $grouping): SelectInterface + { + return $this->setGroups($grouping); + } + public function having(array $having): SelectInterface + { + return $this->setHaving($having); + } + public function orderBy(array $ordering): SelectInterface + { + return $this->setOrders($ordering); + } + + protected array $columns; + public function setColumns(array $columns): SelectInterface + { + foreach ($columns as $column) { + $col = $column; + $alias = null; + if (is_array($column)) { + $col = $column['column'] ?? $column[0]; + $alias = $column['alias'] ?? $column[1]; + } + $this->addColumn($column, $alias); + } + return $this; + } + public function addColumn(string $column, ?string $alias = null): SelectInterface + { + $a = ''; + if ($alias !== null) { + $a = " AS '{$alias}'"; + } + $this->columns[] = "`{$column}`{$a}"; + return $this; + } + public function getColumns(): array + { + return $this->columns; + } + public function getColumnString(): string + { + return implode(', ', $this->getColumns()); + } + protected string $table; + public function setTable(string $table, ?string $alias = null): SelectInterface + { + $table = "`{$table}`"; + if ($alias !== null) { + $table = "{$table} '{$alias}'"; + } + $this->table = $table; + return $this; + } + public function getTable(): string + { + return $this->table; + } + protected array $joins; + public function setJoins(array $joins): SelectInterface + { + foreach ($joins as $join) { + $table = $join['table'] ?? $join[0]; + $expression = $join['expression'] ?? $join[1]; + $this->addJoin($table, $expression); + } + return $this; + } + public function addJoin(string $table, string $expression): SelectInterface + { + $this->joins []= "{$table} ON {$expression}"; + return $this; + } + public function getJoins(): array + { + return $this->joins; + } + public function getJoinString(): string + { + return implode(' ', $this->getJoins()); + } + protected array $conditions; + public function setConditions(array $conditions): SelectInterface + { + foreach ($conditions as $condition) { + $this->addCondition($condition); + } + return $this; + } + public function addCondition(string $expression): SelectInterface + { + $this->conditions []= $expression; + return $this; + } + public function getConditions(): array + { + return $this->conditions; + } + public function getConditionString(): string + { + return implode(' ', $this->getConditions()); + } + protected array $groups; + public function setGroups(array $groups): SelectInterface + { + foreach ($groups as $group) { + $this->addGroup($group); + } + return $this; + } + public function addGroup(string $group): SelectInterface + { + $this->groups []= "`{$group}`"; + return $this; + } + public function getGroups(): array + { + return $this->groups; + } + public function getGroupString(): string + { + return implode(', ', $this->getGroups()); + } + protected array $having; + public function setHaving(array $having): SelectInterface + { + foreach ($having as $item) { + $this->addHaving($item); + } + return $this; + } + public function addHaving(string $having): SelectInterface + { + $this->having []= $having; + return $this; + } + public function getHaving(): array + { + return $this->having; + } + public function getHavingString(): string + { + return implode(', ', $this->getHaving()); + } + protected array $orders; + public function setOrders(array $orders): SelectInterface + { + foreach ($orders as $order) { + $column = $order; + $direction = null; + if (is_array($order)) { + $direction = $order['direction'] ?? $order[1]; + $column = $order['column'] ?? $order[0]; + } + $this->addOrder($column, $direction); + } + return $this; + } + public function addOrder(string $column, ?string $direction = null): SelectInterface + { + if ($direction === null) { + $direction = 'ASC'; + } + $this->orders []= "{$column} {$direction}"; + return $this; + } + public function getOrders(): array + { + return $this->orders; + } + public function getOrderString(): string + { + return implode(', ', $this->getOrders()); + } + + public function build(): string + { + $query = ["SELECT"]; + $query []= $this->getColumnString(); + $query []= "FROM {$this->getTable()}"; + if (isset($this->joins)) { + $query []= $this->getJoinString(); + } + if (isset($this->conditions)) { + $query []= "WHERE {$this->getConditionString()}"; + } + if (isset($this->groups)) { + $query []= "GROUP BY {$this->getGroupString()}"; + } + if (isset($this->having)) { + $query []= "HAVING {$this->getHavingString()}"; + } + if (isset($this->orders)) { + $query []= "ORDER BY {$this->getOrderString()}"; + } + return implode(' ', $query); + } +} diff --git a/src/Alias/Database/Query/Update.php b/src/Alias/Database/Query/Update.php new file mode 100644 index 0000000..e4e0c58 --- /dev/null +++ b/src/Alias/Database/Query/Update.php @@ -0,0 +1,91 @@ +setTable($table); + } + public function set(array $value_pairs): UpdateInterface + { + return $this->setValues($value_pairs); + } + public function where(array $conditions): UpdateInterface + { + return $this->setConditions($conditions); + } + + protected string $table; + public function setTable(string $table): UpdateInterface + { + $this->table = $table; + return $this; + } + public function getTable(): string + { + return $this->table; + } + protected array $values; + public function setValues(array $values): UpdateInterface + { + foreach ($values as $value) { + $column = $value['column'] ?? $value[0]; + $val = $value['value'] ?? $value[1]; + $this->addValue($column, $val); + } + return $this; + } + public function addValue(string $column, int|string $value): UpdateInterface + { + if (!is_numeric($value)) { + $value = "'{$value}'"; + } + $this->values []= "`{$column}` = {$value}"; + return $this; + } + public function getValues(): array + { + return $this->values; + } + public function getValueString(): string + { + return implode(', ', $this->getValues()); + } + protected array $conditions; + public function setConditions(array $conditions): UpdateInterface + { + foreach ($conditions as $condition) { + $this->addCondition($condition); + } + return $this; + } + public function addCondition(string $expression): UpdateInterface + { + $this->conditions []= $expression; + return $this; + } + public function getConditions(): array + { + return $this->conditions; + } + public function getConditionString(): string + { + return implode(' ', $this->getConditions()); + } + + public function build(): string + { + return implode(' ', [ + 'UPDATE', + $this->getTable(), + 'SET', + $this->getValueString(), + 'WHERE', + $this->getConditionString() + ]); + } +} From 6de6720c3e7a27b530ef7686ccf196acafbd0707 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 17:41:21 -0400 Subject: [PATCH 5/6] MySQL Queries --- src/Database/Query/MySQL/Delete.php | 7 ++++ src/Database/Query/MySQL/Insert.php | 7 ++++ src/Database/Query/MySQL/Select.php | 50 +++++++++++++++++++++++++++++ src/Database/Query/MySQL/Update.php | 7 ++++ 4 files changed, 71 insertions(+) create mode 100644 src/Database/Query/MySQL/Delete.php create mode 100644 src/Database/Query/MySQL/Insert.php create mode 100644 src/Database/Query/MySQL/Select.php create mode 100644 src/Database/Query/MySQL/Update.php diff --git a/src/Database/Query/MySQL/Delete.php b/src/Database/Query/MySQL/Delete.php new file mode 100644 index 0000000..fbce5cd --- /dev/null +++ b/src/Database/Query/MySQL/Delete.php @@ -0,0 +1,7 @@ +setLimit($limit); + if ($offset !== null) { + $this->setOffset($offset); + } + return $this; + } + protected int $limit; + public function setLimit(int $limit): Select + { + $this->limit = $limit; + return $this; + } + public function getLimit(): int + { + return $this->limit; + } + protected int $offset; + public function setOffset(int $offset): Select + { + $this->offset = $offset; + return $this; + } + public function getOffset(): int + { + return $this->offset; + } + + public function build(): string + { + $query = [parent::build()]; + if (isset($this->limit)) { + $query []= 'LIMIT'; + $query []= $this->getLimit(); + if (isset($this->offset)) { + $query []= 'OFFSET'; + $query []= $this->getOffset(); + } + } + return implode(' ', $query); + } +} diff --git a/src/Database/Query/MySQL/Update.php b/src/Database/Query/MySQL/Update.php new file mode 100644 index 0000000..26bfa64 --- /dev/null +++ b/src/Database/Query/MySQL/Update.php @@ -0,0 +1,7 @@ + Date: Thu, 8 Sep 2022 17:41:37 -0400 Subject: [PATCH 6/6] Query "Factory" --- src/Database/QueryBuilder.php | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/Database/QueryBuilder.php diff --git a/src/Database/QueryBuilder.php b/src/Database/QueryBuilder.php new file mode 100644 index 0000000..a9bd65e --- /dev/null +++ b/src/Database/QueryBuilder.php @@ -0,0 +1,37 @@ +container = $container; + return $this; + } + public function getContainer(): ContainerInterface + { + return $this->container; + } + + public function select(array $columns = ['*']): Select + { + return $this->getContainer()->get(Select::class)->select($columns); + } + public function insert(string $table): Insert + { + return $this->getContainer()->get(Insert::class)->into($table); + } + public function update(string $table): Update + { + return $this->getContainer()->get(Update::class)->table($table); + } + public function delete(string $table): Delete + { + return $this->getContainer()->get(Delete::class)->from($table); + } +}