diff --git a/composer.json b/composer.json
index 2a3bd38..4dcd184 100644
--- a/composer.json
+++ b/composer.json
@@ -3,7 +3,8 @@
"files": [ "src/classnames/function.php" ],
"psr-4": {
"ClassNames\\": "src/classnames",
- "MergeCoverage\\": "src/merge-coverage"
+ "MergeCoverage\\": "src/merge-coverage",
+ "QueryBuilder\\": "src/query-builder"
}
},
"require-dev": {
diff --git a/phpunit.xml b/phpunit.xml
index 8e37f4a..0e984fa 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -13,6 +13,9 @@
src/classnames/Tests
+
+ src/query-builder/Tests
+
diff --git a/src/query-builder/Column.php b/src/query-builder/Column.php
new file mode 100644
index 0000000..4441a09
--- /dev/null
+++ b/src/query-builder/Column.php
@@ -0,0 +1,20 @@
+alias) {
+ return $this->expression . ' AS ' . $this->alias;
+ }
+ return $this->expression;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/From.php b/src/query-builder/From.php
new file mode 100644
index 0000000..c34920f
--- /dev/null
+++ b/src/query-builder/From.php
@@ -0,0 +1,22 @@
+expression .= PHP_EOL . Query::INDENT . 'JOIN ' . $table . ' ON ' . (string) $condition;
+ }
+
+ public function __toString()
+ {
+ return 'FROM ' . $this->expression;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Join.php b/src/query-builder/Join.php
new file mode 100644
index 0000000..719f88a
--- /dev/null
+++ b/src/query-builder/Join.php
@@ -0,0 +1,20 @@
+table = $table;
+ }
+
+ private function plop($from, $join) {
+
+ }
+
+ public function __toString()
+ {
+ return Query::INDENT . "JOIN " . $this->table . $this->conditions();
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Join/Equals.php b/src/query-builder/Join/Equals.php
new file mode 100644
index 0000000..66d2470
--- /dev/null
+++ b/src/query-builder/Join/Equals.php
@@ -0,0 +1,17 @@
+left . ' = ' . $this->right;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Query.php b/src/query-builder/Query.php
new file mode 100644
index 0000000..8e9aabe
--- /dev/null
+++ b/src/query-builder/Query.php
@@ -0,0 +1,34 @@
+select = $select;
+ $this->from = $from;
+ $this->where = $where;
+ }
+
+ public function __toString()
+ {
+ $parts = [
+ $this->select,
+ $this->from,
+ "WHERE " . $this->where,
+ Query::FINAL_SEMI_COLON,
+ ];
+
+ return implode(PHP_EOL, $parts);
+ }
+}
+
diff --git a/src/query-builder/Select.php b/src/query-builder/Select.php
new file mode 100644
index 0000000..5b294c2
--- /dev/null
+++ b/src/query-builder/Select.php
@@ -0,0 +1,24 @@
+columns = $columns;
+ }
+
+ public function add(Column $column){
+ $this->columns[] = $column;
+ return $this;
+ }
+
+ public function __toString()
+ {
+ $select = implode("," . PHP_EOL . Query::INDENT, $this->columns);
+ return "SELECT" . PHP_EOL . Query::INDENT . $select;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Sum.php b/src/query-builder/Sum.php
new file mode 100644
index 0000000..f10baa5
--- /dev/null
+++ b/src/query-builder/Sum.php
@@ -0,0 +1,21 @@
+expression = 'SUM(' . $this->expression . ')';
+ }
+
+ public function __toString()
+ {
+ if ($this->alias) {
+ return $this->expression . ' AS ' . $this->alias;
+ }
+ return $this->expression;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Table.php b/src/query-builder/Table.php
new file mode 100644
index 0000000..367e198
--- /dev/null
+++ b/src/query-builder/Table.php
@@ -0,0 +1,31 @@
+alias ? $this->name . ' ' . $this->alias : $this->name);
+ }
+
+ public function column(string $expression, ?string $alias = null)
+ {
+ $table = $this->alias ?? $this->name;
+ return new Column($table . '.' . $expression, $alias);
+ }
+
+ public function sum(string $expression, ?string $as = null)
+ {
+ $table = $this->alias ?? $this->name;
+ return new Sum($table . '.' . $expression, $as);
+ }
+
+ public function __toString()
+ {
+ return $this->alias ?? $this->name;
+ }
+}
\ No newline at end of file
diff --git a/src/query-builder/Tests/QueryTest.php b/src/query-builder/Tests/QueryTest.php
new file mode 100644
index 0000000..a61a472
--- /dev/null
+++ b/src/query-builder/Tests/QueryTest.php
@@ -0,0 +1,91 @@
+column('name');
+ }
+ public function id() {
+ return $this->column('id');
+ }
+ public function departement() {
+ return $this->column('departement');
+ }
+ public function departementShouldBe(int $departement) {
+ return new Where\Equals($this->departement(), (string) $departement);
+ }
+
+ public function joins(Table $orders){
+ return $orders->from()->join($this->name, new Equals($orders->customerId(), $this->id()));
+ }
+ };
+
+ $orders = new class('orders') extends Table {
+ public function customerId() {
+ return $this->column('customer_id');
+ }
+ public function id() {
+ return $this->column('id');
+ }
+ public function valid() {
+ return $this->column('valid');
+ }
+ public function shouldBeValid() {
+ return new Where\Equals($this->column('valid'), 'TRUE');
+ }
+ public function total() {
+ return $this->sum('price',as: 'total');
+ }
+ };
+
+ $customerOrders = new class($orders, $customers) extends From {
+ public function __construct($orders, $customers)
+ {
+ parent::__construct('orders');
+ $this->join('customers', new Equals($orders->customerId(), $customers->id()));
+ }
+ };
+
+ $select = new Select(
+ $orders->total(),
+ $customers->name(),
+ );
+
+ $validDepartements = Where::atLeastOne(
+ $customers->departementShouldBe(14),
+ $customers->departementShouldBe(15),
+ );
+ $where = Where::everyOnes(
+ $orders->shouldBeValid(),
+ $validDepartements,
+ );
+
+ $query = new Query($select, $customerOrders, $where);
+
+ $sql = <<expression;
+ }
+}
diff --git a/src/query-builder/Where/Ensemble.php b/src/query-builder/Where/Ensemble.php
new file mode 100644
index 0000000..eb16a8f
--- /dev/null
+++ b/src/query-builder/Where/Ensemble.php
@@ -0,0 +1,19 @@
+expression;
+ }
+}
+
diff --git a/src/query-builder/Where/Equals.php b/src/query-builder/Where/Equals.php
new file mode 100644
index 0000000..04e4ee2
--- /dev/null
+++ b/src/query-builder/Where/Equals.php
@@ -0,0 +1,19 @@
+left . ' = ' . $this->right;
+ }
+}
+