Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,13 @@ class UserRepository extends EntityRecordRepository

```php
insertOne($entry)
selectOneWhere(where: ['id' => 10])
selectOneWhere(where: where(['id' => equalsTo(10)]))
selectOneByQuery(selectQuery: 'SELECT * FROM table where id = :id', bindings: ['id' => 10])
selectManyWhere([where: 'deleted_at' => null], limit: 10, offset: 100)
selectManyWhere(where: where(['deleted_at' => isNull()]), limit: 10, offset: 100)
selectManyByQuery(selectQuery: 'SELECT * FROM table where deleted_at is null', bindings: [])
existsWhere(where: ['id' => 10])
deleteWhere(where: ['id' => 10])
updateWhere(values: ['name' => 'Arthur Dent', 'date_of_birth' => '1990-01-01'], where: ['id' => 10])
existsWhere(where: where(['id' => equalsTo(10)]))
deleteWhere(where: where(['id' => equalsTo(10)]))
updateWhere(values: ['name' => 'Arthur Dent', 'date_of_birth' => '1990-01-01'], where: where(['id' => equalsTo(10)]))
```

📙 `EntityRecordRepository` extends RecordRepository with additional features for managing entity lifecycles:
Expand All @@ -260,11 +260,6 @@ Contributions are welcome! If you have ideas, find a bug, or want to improve the

Please follow PSR-12 coding standards and ensure tests pass before submitting changes.

## 🚀 Next steps

- Query builder
- Extend where comparisons

## 📄 License

This project is open-sourced under the [MIT license](LICENSE).
Expand Down
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
"autoload": {
"psr-4": {
"Tcds\\Io\\Orm\\": "src/"
}
},
"files": [
"src/Functions/query.php"
]
},
"autoload-dev": {
"psr-4": {
Expand Down
18 changes: 9 additions & 9 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Connection/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

interface Connection
{
public function driver(): ConnectionDriver;
public function driver(): Driver;

public function begin(): void;

Expand Down
11 changes: 0 additions & 11 deletions src/Connection/ConnectionDriver.php

This file was deleted.

19 changes: 19 additions & 0 deletions src/Connection/Driver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Tcds\Io\Orm\Connection;

enum Driver
{
case GENERIC;
case MYSQL;

public function wrap(string $column): string
{
return match ($this) {
Driver::MYSQL => "`$column`",
Driver::GENERIC => "$column",
};
}
}
6 changes: 3 additions & 3 deletions src/Connection/Pdo/MysqlConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Tcds\Io\Orm\Connection\Pdo;

use PDO;
use Tcds\Io\Orm\Connection\ConnectionDriver;
use Tcds\Io\Orm\Connection\Driver;

class MysqlConnection extends NestedTransactionConnection
{
Expand All @@ -17,8 +17,8 @@ public function __construct(PDO $read, PDO $write)
parent::__construct($read, $write);
}

public function driver(): ConnectionDriver
public function driver(): Driver
{
return ConnectionDriver::MYSQL;
return Driver::MYSQL;
}
}
19 changes: 16 additions & 3 deletions src/EntityRecordRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tcds\Io\Orm;

use Tcds\Io\Orm\Connection\Connection;
use Tcds\Io\Orm\Query\Query;

/**
* @template EntryType
Expand All @@ -28,7 +29,7 @@ public function __construct(
*/
public function selectEntityById($id)
{
return $this->selectOneWhere(['id' => $id]);
return $this->selectOneWhere(where(['id' => equalsTo($id)]));
}

/**
Expand All @@ -38,7 +39,7 @@ public function updateOne($entity): void
{
$this->updateWhere(
$this->mapper->plain($entity),
['id' => $this->entityMapper->primaryKey->plain($entity)],
$this->equalsToPrimaryKey($entity),
);
}

Expand All @@ -57,7 +58,9 @@ public function updateMany(...$entities): void
*/
public function deleteOne($entity): void
{
$this->deleteWhere(['id' => $this->entityMapper->primaryKey->plain($entity)]);
$this->deleteWhere(
$this->equalsToPrimaryKey($entity),
);
}

/**
Expand All @@ -69,4 +72,14 @@ public function deleteMany(...$entities): void
$this->deleteOne($entity);
}
}

/**
* @param EntryType $entity
*/
private function equalsToPrimaryKey($entity): Query
{
return where([
'id' => equalsTo($this->entityMapper->primaryKey->plain($entity)),
]);
}
}
92 changes: 92 additions & 0 deletions src/Functions/query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

use Tcds\Io\Orm\Query\Conditions\FilteringCondition;
use Tcds\Io\Orm\Query\Query;

/**
* @param array<string, FilteringCondition> $where
* @return Query
*/
function where(array $where): Query
{
$query = null;

foreach ($where as $column => $condition) {
$query === null
? $query = Query::where($column, $condition)
: $query->and($column, $condition);
}

return $query;

Check failure on line 22 in src/Functions/query.php

View workflow job for this annotation

GitHub Actions / build

Function where() should return Tcds\Io\Orm\Query\Query but returns Tcds\Io\Orm\Query\Query|null.
}

function between(mixed $first, mixed $last): FilteringCondition
{
return new FilteringCondition('BETWEEN ? AND ?', [$first, $last]);
}

function differentOf(mixed $value): FilteringCondition
{
return new FilteringCondition('!= ?', [$value]);
}

function equalsTo(mixed $value): FilteringCondition
{
return new FilteringCondition('= ?', [$value]);
}

function greaterThan(mixed $value): FilteringCondition
{
return new FilteringCondition('> ?', [$value]);
}

function greaterThanOrEqualTo(mixed $value): FilteringCondition
{
return new FilteringCondition('>= ?', [$value]);
}

function in(array $values): FilteringCondition

Check failure on line 50 in src/Functions/query.php

View workflow job for this annotation

GitHub Actions / build

Function in() has parameter $values with no value type specified in iterable type array.
{
$marks = join(',', array_fill(0, count($values), '?'));

return new FilteringCondition("IN ($marks)", $values);
}

function isNotNull(): FilteringCondition
{
return new FilteringCondition('IS NOT NULL', []);
}

function isNull(): FilteringCondition
{
return new FilteringCondition('IS NULL', []);
}

function like(mixed $value): FilteringCondition
{
return new FilteringCondition('LIKE ?', [$value]);
}

function notIn(array $values): FilteringCondition

Check failure on line 72 in src/Functions/query.php

View workflow job for this annotation

GitHub Actions / build

Function notIn() has parameter $values with no value type specified in iterable type array.
{
$marks = join(',', array_fill(0, count($values), '?'));

return new FilteringCondition("NOT IN ($marks)", $values);
}

function notLike(mixed $value): FilteringCondition
{
return new FilteringCondition('NOT LIKE ?', [$value]);
}

function smallerThan(mixed $value): FilteringCondition
{
return new FilteringCondition('< ?', [$value]);
}

function smallerThanOrEqualTo(mixed $value): FilteringCondition
{
return new FilteringCondition('<= ?', [$value]);
}
15 changes: 15 additions & 0 deletions src/Query/Conditions/Condition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Tcds\Io\Orm\Query\Conditions;

use Tcds\Io\Orm\Connection\Driver;

interface Condition
{
/**
* @return array{0: string, 1: list<mixed>}
*/
public function build(Driver $driver): array;
}
24 changes: 24 additions & 0 deletions src/Query/Conditions/ConditionList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Tcds\Io\Orm\Query\Conditions;

use Tcds\Io\Generic\MutableArrayList;
use Tcds\Io\Orm\Query\Operator;

/**
* @extends MutableArrayList<array{0: Operator, 1: Condition}>
*/
class ConditionList extends MutableArrayList
{
public function __construct()
{
parent::__construct([]);
}

public function add(Operator $operator, Condition $condition): void
{
$this->push([$operator, $condition]);
}
}
24 changes: 24 additions & 0 deletions src/Query/Conditions/FieldCondition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Tcds\Io\Orm\Query\Conditions;

use Tcds\Io\Orm\Connection\Driver;

readonly class FieldCondition implements Condition
{
public function __construct(
private string $column,
private FilteringCondition $condition,
) {
}

public function build(Driver $driver): array
{
$column = $driver->wrap($this->column);
[$query, $params] = $this->condition->build($driver);

return ["$column $query", $params];
}
}
26 changes: 26 additions & 0 deletions src/Query/Conditions/FilteringCondition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tcds\Io\Orm\Query\Conditions;

use Override;
use Tcds\Io\Orm\Connection\Driver;

readonly class FilteringCondition implements Condition
{
final public function __construct(
protected string $comparator,
/** @var array<mixed> */
protected array $params = [],
) {
}

#[Override] public function build(Driver $driver): array
{
return [

Check failure on line 21 in src/Query/Conditions/FilteringCondition.php

View workflow job for this annotation

GitHub Actions / build

Method Tcds\Io\Orm\Query\Conditions\FilteringCondition::build() should return array{string, list<mixed>} but returns array{string, array<mixed>}.
$this->comparator,
$this->params,
];
}
}
Loading
Loading