diff --git a/src/Collection.php b/src/Collection.php index da25b3e..d0dc73b 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -37,6 +37,19 @@ class Collection implements IteratorAggregate, Countable return count($this->elements) == 0; } + public function index($index): mixed + { + if (isset($this->elements[$index])) { + return $this->elements[$index]; + } + return null; + } + + public function random(): mixed + { + return array_rand($this->elements); + } + public function reduce(callable $fn, mixed $initial): mixed { return array_reduce($this->elements, $fn, $initial); diff --git a/src/Expression.php b/src/Expression.php index 803a024..27d451e 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -25,9 +25,21 @@ class Expression if ($operator == "between" && count($this->value) == 2) { return "(" . $this->condition . " " . $this->operator . " ? AND ? )"; } + if ($operator == "notnull") { + return "(" . $this->condition . " IS NOT NULL )"; + } + if ($operator == "isnull") { + return "(" . $this->condition . " IS NULL )"; + } return "(" . $this->condition . " " . $this->operator . " ? )"; } + public function hasData() + { + $operator = trim(strtolower($this->operator)); + return (in_array($operator, ["isnull","notnull"])) ? false : true; + } + public function getCondition() { return $this->condition; diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index ced14e5..c521785 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -15,6 +15,7 @@ class QueryBuilder protected ?int $take; protected ?int $offset; protected string $raw_query; + protected bool $distinct; public function __construct($table, $pk = "id", $connection = "default") { @@ -33,6 +34,7 @@ class QueryBuilder $this->groupby = []; $this->offset = null; $this->take = null; + $this->distinct = false; $this->raw_query = ""; } @@ -54,6 +56,12 @@ class QueryBuilder return $this; } + public function distinct() + { + $this->distinct = true; + return $this; + } + public function orderBy($columns, $sort = "ASC") { if (is_array($columns)) { @@ -100,6 +108,18 @@ class QueryBuilder return $this; } + public function whereNotNull($condition) + { + $this->wheres[] = new Expression($condition, "notnull", ""); + return $this; + } + + public function whereNull($condition) + { + $this->wheres[] = new Expression($condition, "isnull", ""); + return $this; + } + public function where($condition, $operator, $value = null) { if ($value === null) { @@ -172,7 +192,7 @@ class QueryBuilder $model = new Model(); $ret[] = $model->setPk($this->pk)->setTable($this->table)->fillData($row); } - return new Collection($ret); + return new Collection($ret); } private function getData(): mixed @@ -192,7 +212,8 @@ class QueryBuilder } $columns = implode(",", $this->columns); - $query = "SELECT " . $columns . " FROM " . $this->table ; + $distinct = ($this->distinct) ? " DISTINCT " : ""; + $query = "SELECT " . $distinct . " " . $columns . " FROM " . $this->table ; $where = $this->getWhere(); $this->fillData($ret); @@ -213,7 +234,9 @@ class QueryBuilder { foreach ($this->wheres as $expression) { if ($expression instanceof Expression) { - $query->addData($expression->getValue()); + if ($expression->hasData()) { + $query->addData($expression->getValue()); + } } } } diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php index afe80ac..58a443b 100644 --- a/tests/CollectionTest.php +++ b/tests/CollectionTest.php @@ -14,6 +14,8 @@ test("collection", function () { expect($coll->count())->toBe(11); expect($coll->first())->toBe(0); expect($coll->last())->toBe(10); + expect($coll->index(1))->toBe(1); + expect($coll->random())->toBeGreaterThanOrEqual(0)->toBeLessThanOrEqual(11); $filt = $coll->filter(function($item){ return $item<5;}); expect($filt)->toBeInstanceOf(Collection::class); diff --git a/tests/DbTest.php b/tests/DbTest.php index 5690a21..727beaa 100644 --- a/tests/DbTest.php +++ b/tests/DbTest.php @@ -64,6 +64,14 @@ test("querybuilder", function() { $rows = $qb->whereRaw("id = 1")->get(); expect($rows)->toBeInstanceOf(Collection::class); expect(count($rows))->toBe(1); + + $qb->reset(); + $rows = $qb->distinct()->get(); + expect(count($rows))->toBe(2); + + $qb->reset(); + $rows = $qb->whereNotNull("col1")->get(); + expect(count($rows))->toBe(2); }); test("order by", function(){ @@ -91,6 +99,8 @@ test("group by", function(){ expect($rows->first()->Nb)->toBe(1); }); + + test("update row", function() { $qb = new QueryBuilder("test","id"); $row = $qb->find(1); @@ -144,6 +154,22 @@ test("where array", function() { }); +test("is null", function(){ + $row4 = new Model(); + $row4->setTable("test"); + $row4->col1 = null; + $row4->date1 = new \DateTime(); + $ret4 = $row4->save(); + expect($ret4)->toBe(true); + + $qb = new QueryBuilder("test"); + $rows = $qb->whereNull("col1")->get(); + + expect($rows)->toBeInstanceOf(Collection::class); + expect(count($rows))->toBe(1); + expect($rows->first()->col1)->toBe(null); +}); + test("second connection", function() { $row = new Model(); $row->setConnection("contwo");