Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8e81822
docs: update changelog
obarbosa89 Oct 6, 2024
c5c32a6
refactor: change property visibility
obarbosa89 Oct 6, 2024
10f1e7a
feat: initial basic data modeling
obarbosa89 Oct 6, 2024
b9ea7e9
feat: add model collection class
obarbosa89 Oct 6, 2024
827faa6
feat: load belongsTo relationship
obarbosa89 Oct 14, 2024
9b0f234
feat: query builder method as optional in model class
obarbosa89 Oct 14, 2024
50e8c7e
feat: caching model key property
obarbosa89 Oct 14, 2024
7e37140
feat: has many relationship
obarbosa89 Oct 18, 2024
9d8aecb
style: phpcs
obarbosa89 Oct 18, 2024
61d1983
feat: create relationship builders
obarbosa89 Oct 23, 2024
3a6e01e
feat: load children without chaperone
obarbosa89 Oct 28, 2024
d2f5970
feat: load relationship with chaperone
obarbosa89 Oct 28, 2024
68d64f8
feat: load chaperone from relationship method
obarbosa89 Oct 30, 2024
73c34d7
feat: load relationship with column selection
obarbosa89 Nov 5, 2024
6bc7179
feat: create alias from key and value on select columns
obarbosa89 Nov 17, 2024
ff59043
feat: belongs to many relationship
obarbosa89 Nov 17, 2024
54fb986
feat: select pivot columns
obarbosa89 Nov 19, 2024
ca73363
feat: load belongs to many relationship with column selection
obarbosa89 Nov 20, 2024
27d470c
feat: shot syntax to select relationship columns
obarbosa89 Nov 20, 2024
3cdb150
feat: relationship parser
obarbosa89 Dec 10, 2024
017bd4c
feat: split columns from relationship name
obarbosa89 Dec 10, 2024
c590dd3
refactor: remove parent param
obarbosa89 Dec 11, 2024
7b3aca6
feat: parse nested relationship
obarbosa89 Dec 12, 2024
d30212e
feat: load nested relationships
obarbosa89 Dec 12, 2024
f4ec843
feat: add array method
obarbosa89 Dec 12, 2024
f5254f4
refactor: import functions
obarbosa89 Dec 12, 2024
030d480
chore: remove comments
obarbosa89 Dec 12, 2024
8a26680
fix: solve phpstan errors
obarbosa89 Dec 12, 2024
ee87ca2
fix: phpstan errors
obarbosa89 Dec 12, 2024
785bcf0
fix: phpstan issues
obarbosa89 Dec 12, 2024
e2e3d87
test: arr utility
obarbosa89 Dec 12, 2024
be90df3
test: arr first and wrap methods
obarbosa89 Dec 12, 2024
417174e
test: arr exists method
obarbosa89 Dec 12, 2024
9e83c79
test: method toArray of model collection
obarbosa89 Dec 12, 2024
f8a4d72
test: first method of collection
obarbosa89 Dec 12, 2024
9afefda
refactor: remove docblock
obarbosa89 Dec 12, 2024
b0578cf
test: instance type in model property
obarbosa89 Dec 13, 2024
12d6427
test: set custom connection
obarbosa89 Dec 13, 2024
0dee18f
refactor: share code between query builders
obarbosa89 Dec 13, 2024
7a7e712
style: phpcs
obarbosa89 Dec 13, 2024
cc32808
fix: count records with clauses
obarbosa89 Dec 13, 2024
f197e97
test: check exceptions
obarbosa89 Dec 13, 2024
6a9ce5a
fix: normalize type before create instance
obarbosa89 Dec 13, 2024
e5f7d28
test: model to array
obarbosa89 Dec 13, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [v0.4.0 (2024-09-27)](https://github.com/phenixphp/framework/compare/0.3.8...0.4.0)

### Added
- Integrate CORS middleware. ([#30](https://github.com/phenixphp/framework/pull/30))
- Add basic form request. ([#31](https://github.com/phenixphp/framework/pull/31))
- Basic validation layer using form request. ([#32](https://github.com/phenixphp/framework/pull/32))
- Stream form parser. ([#33](https://github.com/phenixphp/framework/pull/33))
- Move validation layer to framework. ([#34](https://github.com/phenixphp/framework/pull/34))
Expand Down
12 changes: 6 additions & 6 deletions src/Configurations/Cors.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

class Cors extends Configuration
{
public readonly array|string $origins;
public readonly array $allowedMethods;
public readonly int $maxAge;
public readonly array $allowedHeaders;
public readonly array $exposableHeaders;
public readonly bool $allowCredentials;
protected array|string $origins;
protected array $allowedMethods;
protected int $maxAge;
protected array $allowedHeaders;
protected array $exposableHeaders;
protected bool $allowCredentials;

public function __construct(array $config)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Contracts/Database/ModelAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Phenix\Contracts\Database;

interface ModelAttribute
{
public function getColumnName(): string|null;
}
13 changes: 13 additions & 0 deletions src/Data/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use Ramsey\Collection\Collection as GenericCollection;
use SplFixedArray;

use function array_key_first;

class Collection extends GenericCollection implements Arrayable
{
public static function fromArray(array $data): self
Expand All @@ -21,4 +23,15 @@ public static function fromArray(array $data): self

return $collection;
}

public function first(): mixed
{
$firstIndex = array_key_first($this->data);

if ($firstIndex === null) {
return null;
}

return $this->data[$firstIndex];
}
}
114 changes: 114 additions & 0 deletions src/Database/Concerns/Query/HasSentences.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Concerns\Query;

use Amp\Sql\SqlQueryError;
use Amp\Sql\SqlTransactionError;
use League\Uri\Components\Query;
use League\Uri\Http;
use Phenix\Database\Constants\Actions;
use Phenix\Database\Paginator;

trait HasSentences
{
public function paginate(Http $uri, int $defaultPage = 1, int $defaultPerPage = 15): Paginator
{
$this->action = Actions::SELECT;

$query = Query::fromUri($uri);

$currentPage = filter_var($query->get('page') ?? $defaultPage, FILTER_SANITIZE_NUMBER_INT);
$currentPage = $currentPage === false ? $defaultPage : $currentPage;

$perPage = filter_var($query->get('per_page') ?? $defaultPerPage, FILTER_SANITIZE_NUMBER_INT);
$perPage = $perPage === false ? $defaultPerPage : $perPage;

$countQuery = clone $this;

$total = $countQuery->count();

$data = $this->page((int) $currentPage, (int) $perPage)->get();

return new Paginator($uri, $data, (int) $total, (int) $currentPage, (int) $perPage);
}

public function count(string $column = '*'): int
{
$this->action = Actions::SELECT;

$this->countRows($column);

[$dml, $params] = $this->toSql();

/** @var array<string, int> $count */
$count = $this->connection
->prepare($dml)
->execute($params)
->fetchRow();

return array_values($count)[0];
}

public function insert(array $data): bool
{
[$dml, $params] = $this->insertRows($data)->toSql();

try {
$this->connection->prepare($dml)->execute($params);

return true;
} catch (SqlQueryError|SqlTransactionError) {
return false;
}
}

public function exists(): bool
{
$this->action = Actions::EXISTS;

$this->existsRows();

[$dml, $params] = $this->toSql();

$results = $this->connection->prepare($dml)->execute($params)->fetchRow();

return (bool) array_values($results)[0];
}

public function doesntExist(): bool
{
return ! $this->exists();
}

public function update(array $values): bool
{
$this->updateRow($values);

[$dml, $params] = $this->toSql();

try {
$this->connection->prepare($dml)->execute($params);

return true;
} catch (SqlQueryError|SqlTransactionError) {
return false;
}
}

public function delete(): bool
{
$this->deleteRows();

[$dml, $params] = $this->toSql();

try {
$this->connection->prepare($dml)->execute($params);

return true;
} catch (SqlQueryError|SqlTransactionError) {
return false;
}
}
}
16 changes: 10 additions & 6 deletions src/Database/Concerns/Query/PrepareColumns.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@

namespace Phenix\Database\Concerns\Query;

use Phenix\Database\Alias;
use Phenix\Database\Functions;
use Phenix\Database\SelectCase;
use Phenix\Database\Subquery;
use Phenix\Exceptions\QueryError;
use Phenix\Util\Arr;

use function is_string;

trait PrepareColumns
{
protected function prepareColumns(array $columns): string
{
$columns = array_map(function ($column) {
$columns = Arr::map($columns, function (string|Functions|SelectCase|Subquery $value, int|string $key): string {
return match (true) {
$column instanceof Functions => (string) $column,
$column instanceof SelectCase => (string) $column,
$column instanceof Subquery => $this->resolveSubquery($column),
default => $column,
is_string($key) => (string) Alias::of($key)->as($value),
$value instanceof Functions => (string) $value,
$value instanceof SelectCase => (string) $value,
$value instanceof Subquery => $this->resolveSubquery($value),
default => $value,
};
}, $columns);
});

return Arr::implodeDeeply($columns, ', ');
}
Expand Down
11 changes: 11 additions & 0 deletions src/Database/Constants/IdType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Constants;

enum IdType
{
case NUMERIC;
case STR;
}
17 changes: 17 additions & 0 deletions src/Database/Models/Attributes/BelongsTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class BelongsTo extends Column
{
public function __construct(
public string $foreignProperty,
public string|null $name = null,
) {
}
}
24 changes: 24 additions & 0 deletions src/Database/Models/Attributes/BelongsToMany.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class BelongsToMany extends Column
{
public function __construct(
public string $table,
public string $foreignKey,
public string $relatedModel,
public string $relatedForeignKey,
) {
}

public function getColumnName(): string|null
{
return null;
}
}
21 changes: 21 additions & 0 deletions src/Database/Models/Attributes/Column.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class Column extends ModelAttribute
{
public function __construct(
public string|null $name = null
) {
}

public function getColumnName(): string|null
{
return $this->name;
}
}
12 changes: 12 additions & 0 deletions src/Database/Models/Attributes/ForeignKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class ForeignKey extends Column
{
}
23 changes: 23 additions & 0 deletions src/Database/Models/Attributes/HasMany.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class HasMany extends Column
{
public function __construct(
public string $model,
public string $foreignKey,
public bool $chaperone = false,
) {
}

public function getColumnName(): string|null
{
return null;
}
}
18 changes: 18 additions & 0 deletions src/Database/Models/Attributes/Id.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Attribute;
use Phenix\Database\Constants\IdType;

#[Attribute(Attribute::TARGET_PROPERTY)]
readonly class Id extends Column
{
public function __construct(
public string|null $name = null,
public IdType $idType = IdType::NUMERIC
) {
}
}
11 changes: 11 additions & 0 deletions src/Database/Models/Attributes/ModelAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models\Attributes;

use Phenix\Contracts\Database\ModelAttribute as ModelAttributeContract;

abstract readonly class ModelAttribute implements ModelAttributeContract
{
}
38 changes: 38 additions & 0 deletions src/Database/Models/Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Phenix\Database\Models;

use Phenix\Data\Collection as DataCollection;

class Collection extends DataCollection
{
public function __construct(array $data = [])
{
parent::__construct(DatabaseModel::class, $data);
}

public function modelKeys(): array
{
return $this->reduce(function (array $carry, DatabaseModel $model): array {
$carry[] = $model->getKey();

return $carry;
}, []);
}

public function map(callable $callback): self
{
return new self(array_map($callback, $this->data));
}

public function toArray(): array
{
return $this->reduce(function (array $carry, DatabaseModel $model): array {
$carry[] = $model->toArray();

return $carry;
}, []);
}
}
Loading
Loading