{"id":30146543,"url":"https://github.com/apioo/psx-sql","last_synced_at":"2025-08-11T09:39:16.859Z","repository":{"id":49554332,"uuid":"55151352","full_name":"apioo/psx-sql","owner":"apioo","description":"Generate type-safe PHP classes from your database","archived":false,"fork":false,"pushed_at":"2025-05-24T11:49:30.000Z","size":411,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-30T20:44:20.897Z","etag":null,"topics":["database","generator","php","sql","table","type-safe"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apioo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"chriskapp","patreon":"fusio","custom":"https://www.paypal.me/fusioapi"}},"created_at":"2016-03-31T13:07:35.000Z","updated_at":"2025-05-24T11:47:32.000Z","dependencies_parsed_at":"2024-02-18T21:28:31.956Z","dependency_job_id":"22278403-3d23-446e-94bf-d28eccbb3505","html_url":"https://github.com/apioo/psx-sql","commit_stats":{"total_commits":191,"total_committers":2,"mean_commits":95.5,"dds":"0.31413612565445026","last_synced_commit":"c5ea46a4819ca0363c6c25af2ec2d530e53f768b"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/apioo/psx-sql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apioo%2Fpsx-sql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apioo%2Fpsx-sql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apioo%2Fpsx-sql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apioo%2Fpsx-sql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apioo","download_url":"https://codeload.github.com/apioo/psx-sql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apioo%2Fpsx-sql/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269864141,"owners_count":24487576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","generator","php","sql","table","type-safe"],"created_at":"2025-08-11T09:39:12.168Z","updated_at":"2025-08-11T09:39:16.833Z","avatar_url":"https://github.com/apioo.png","language":"PHP","readme":"\n# Sql\n\nThis library generates type-safe PHP classes from your database tables and thus allows you to interact with your\ndatabase in a complete type-safe way.\n\n## About\n\nIn traditional ORMs you write a class add specific metadata and generate based on this class your tables, this means our\nsource code defines how a table should look. This library thinks the other way around (database first), this means you\nfirst build your database schema i.e. through a tool like doctrine migrations and then you can use this library to\nautomatically generate all repository and model classes based on the table schema. This has the great advantage that we\ncan generate completely typed repositories. We automatically generate a class for each row (entity) and a repository\nwhich accepts this row. This concept is not new and the Java world has i.e. jOOQ which also follows this idea. It of\ncourse means also that you need to regenerate your classes if you change your schema.\n\n## Generate\n\nTo generate the table and row classes you can either integrate the `PSX\\Command\\GenerateCommand` into your Symfony\nconsole app or you can also do this programmatically through the `PSX\\Sql\\Generator` class s.\n\n```php\n\u003c?php\n\nuse PSX\\Sql\\Generator\\Generator;\n\n$connection = null; // a doctrine DBAL connection\n$target = __DIR__;\n\n$generator = new Generator($connection, 'Acme\\\\Table');\nforeach ($generator-\u003egenerate() as $className =\u003e $source) {\n    file_put_contents($target . '/' . $className . '.php', '\u003c?php' . \"\\n\\n\" . $source);\n}\n\n```\n\n## Basic usage\n\nThe following are basic examples how you can work with a generated table class.\n\n```php\n\u003c?php\n\nuse PSX\\Sql\\Condition;\nuse PSX\\Sql\\OrderBy;\nuse PSX\\Sql\\TableManager;\nuse PSX\\Sql\\Tests\\Generator\\SqlTableTestTable;\nuse PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn;\nuse PSX\\Sql\\Tests\\Generator\\SqlTableTestRow;\n\n$connection   = null; // a doctrine DBAL connection\n$tableManager = new TableManager($connection);\n\n/** @var SqlTableTestTable $table */\n$table = $tableManager-\u003egetTable(SqlTableTestTable::class);\n\n// returns by default 16 entries from the table ordered by the primary column descending\n$table-\u003efindAll();\n\n// returns 12 entries starting at index 0\n$table-\u003efindAll(startIndex: 0, count: 12);\n\n// orders the entries after the column \"id\" descending\n$table-\u003efindAll(startIndex: 0, count: 12, sortBy: SqlTableTestColumn::ID, sortOrder: OrderBy::DESC);\n\n// returns all rows which match the specified title\n$table-\u003efindByTitle('foo%');\n\n// returns a row by the primary key\n$table-\u003efind(1);\n\n// returns the count of entries in the table. It is also possible to provide a condition\n$table-\u003egetCount();\n\n// creates a new row\n$row = new SqlTableTestRow();\n$row-\u003esetTitle('foo');\n$table-\u003ecreate($row);\n\n// updates a row\n$row = $table-\u003efind(1);\n$row-\u003esetTitle('bar');\n$table-\u003eupdate($row);\n\n// deletes a row\n$row = $table-\u003efind(1);\n$table-\u003edelete($row);\n\n```\n\n## Table\n\nThe following is an example of a generated table class.\n\n```php\n\u003c?php\n\nnamespace PSX\\Sql\\Tests\\Generator;\n\n/**\n * @extends \\PSX\\Sql\\TableAbstract\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n */\nclass SqlTableTestTable extends \\PSX\\Sql\\TableAbstract\n{\n    public const NAME = 'psx_sql_table_test';\n    public const COLUMN_ID = 'id';\n    public const COLUMN_TITLE = 'title';\n    public const COLUMN_DATE = 'date';\n    public function getName(): string\n    {\n        return self::NAME;\n    }\n    public function getColumns(): array\n    {\n        return [self::COLUMN_ID =\u003e 0x3020000a, self::COLUMN_TITLE =\u003e 0xa00020, self::COLUMN_DATE =\u003e 0x800000];\n    }\n    /**\n     * @return array\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findAll(?\\PSX\\Sql\\Condition $condition = null, ?int $startIndex = null, ?int $count = null, ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn $sortBy = null, ?\\PSX\\Sql\\OrderBy $sortOrder = null): array\n    {\n        return $this-\u003edoFindAll($condition, $startIndex, $count, $sortBy, $sortOrder);\n    }\n    /**\n     * @return array\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findBy(\\PSX\\Sql\\Condition $condition, ?int $startIndex = null, ?int $count = null, ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn $sortBy = null, ?\\PSX\\Sql\\OrderBy $sortOrder = null): array\n    {\n        return $this-\u003edoFindBy($condition, $startIndex, $count, $sortBy, $sortOrder);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findOneBy(\\PSX\\Sql\\Condition $condition): ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        return $this-\u003edoFindOneBy($condition);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function find(int $id): ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('id', $id);\n        return $this-\u003edoFindOneBy($condition);\n    }\n    /**\n     * @return array\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findById(int $value, ?int $startIndex = null, ?int $count = null, ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn $sortBy = null, ?\\PSX\\Sql\\OrderBy $sortOrder = null): array\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('id', $value);\n        return $this-\u003edoFindBy($condition, $startIndex, $count, $sortBy, $sortOrder);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findOneById(int $value): ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('id', $value);\n        return $this-\u003edoFindOneBy($condition);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function updateById(int $value, \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('id', $value);\n        return $this-\u003edoUpdateBy($condition, $record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function deleteById(int $value): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('id', $value);\n        return $this-\u003edoDeleteBy($condition);\n    }\n    /**\n     * @return array\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findByTitle(string $value, ?int $startIndex = null, ?int $count = null, ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn $sortBy = null, ?\\PSX\\Sql\\OrderBy $sortOrder = null): array\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003elike('title', $value);\n        return $this-\u003edoFindBy($condition, $startIndex, $count, $sortBy, $sortOrder);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findOneByTitle(string $value): ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003elike('title', $value);\n        return $this-\u003edoFindOneBy($condition);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function updateByTitle(string $value, \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003elike('title', $value);\n        return $this-\u003edoUpdateBy($condition, $record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function deleteByTitle(string $value): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003elike('title', $value);\n        return $this-\u003edoDeleteBy($condition);\n    }\n    /**\n     * @return array\u003c\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\u003e\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findByDate(\\PSX\\DateTime\\LocalDateTime $value, ?int $startIndex = null, ?int $count = null, ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestColumn $sortBy = null, ?\\PSX\\Sql\\OrderBy $sortOrder = null): array\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('date', $value);\n        return $this-\u003edoFindBy($condition, $startIndex, $count, $sortBy, $sortOrder);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\QueryException\n     */\n    public function findOneByDate(\\PSX\\DateTime\\LocalDateTime $value): ?\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('date', $value);\n        return $this-\u003edoFindOneBy($condition);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function updateByDate(\\PSX\\DateTime\\LocalDateTime $value, \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('date', $value);\n        return $this-\u003edoUpdateBy($condition, $record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function deleteByDate(\\PSX\\DateTime\\LocalDateTime $value): int\n    {\n        $condition = \\PSX\\Sql\\Condition::withAnd();\n        $condition-\u003eequals('date', $value);\n        return $this-\u003edoDeleteBy($condition);\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function create(\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        return $this-\u003edoCreate($record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function update(\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        return $this-\u003edoUpdate($record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function updateBy(\\PSX\\Sql\\Condition $condition, \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        return $this-\u003edoUpdateBy($condition, $record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function delete(\\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow $record): int\n    {\n        return $this-\u003edoDelete($record-\u003etoRecord());\n    }\n    /**\n     * @throws \\PSX\\Sql\\Exception\\ManipulationException\n     */\n    public function deleteBy(\\PSX\\Sql\\Condition $condition): int\n    {\n        return $this-\u003edoDeleteBy($condition);\n    }\n    /**\n     * @param array\u003cstring, mixed\u003e $row\n     */\n    protected function newRecord(array $row): \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow\n    {\n        return \\PSX\\Sql\\Tests\\Generator\\SqlTableTestRow::from($row);\n    }\n}\n```\n\n## Row\n\nThe following is an example of a generated table row.\n\n```php\n\u003c?php\n\nnamespace PSX\\Sql\\Tests\\Generator;\n\nclass SqlTableTestRow implements \\JsonSerializable, \\PSX\\Record\\RecordableInterface\n{\n    private ?int $id = null;\n    private ?string $title = null;\n    private ?\\PSX\\DateTime\\LocalDateTime $date = null;\n    public function setId(int $id): void\n    {\n        $this-\u003eid = $id;\n    }\n    public function getId(): int\n    {\n        return $this-\u003eid ?? throw new \\PSX\\Sql\\Exception\\NoValueAvailable('No value for required column \"id\" was provided');\n    }\n    public function setTitle(string $title): void\n    {\n        $this-\u003etitle = $title;\n    }\n    public function getTitle(): string\n    {\n        return $this-\u003etitle ?? throw new \\PSX\\Sql\\Exception\\NoValueAvailable('No value for required column \"title\" was provided');\n    }\n    public function setDate(\\PSX\\DateTime\\LocalDateTime $date): void\n    {\n        $this-\u003edate = $date;\n    }\n    public function getDate(): \\PSX\\DateTime\\LocalDateTime\n    {\n        return $this-\u003edate ?? throw new \\PSX\\Sql\\Exception\\NoValueAvailable('No value for required column \"date\" was provided');\n    }\n    public function toRecord(): \\PSX\\Record\\RecordInterface\n    {\n        /** @var \\PSX\\Record\\Record\u003cmixed\u003e $record */\n        $record = new \\PSX\\Record\\Record();\n        $record-\u003eput('id', $this-\u003eid);\n        $record-\u003eput('title', $this-\u003etitle);\n        $record-\u003eput('date', $this-\u003edate);\n        return $record;\n    }\n    public function jsonSerialize(): object\n    {\n        return (object) $this-\u003etoRecord()-\u003egetAll();\n    }\n    public static function from(array|\\ArrayAccess $data): self\n    {\n        $row = new self();\n        $row-\u003eid = isset($data['id']) \u0026\u0026 is_int($data['id']) ? $data['id'] : null;\n        $row-\u003etitle = isset($data['title']) \u0026\u0026 is_string($data['title']) ? $data['title'] : null;\n        $row-\u003edate = isset($data['date']) \u0026\u0026 $data['date'] instanceof \\DateTimeInterface ? \\PSX\\DateTime\\LocalDateTime::from($data['date']) : null;\n        return $row;\n    }\n}\n```\n\n## Column\n\nThe following is an example of a generated table column.\n\n```php\n\u003c?php\n\nnamespace PSX\\Sql\\Tests\\Generator;\n\nenum SqlTableTestColumn : string implements \\PSX\\Sql\\ColumnInterface\n{\n    case ID = \\PSX\\Sql\\Tests\\Generator\\SqlTableTestTable::COLUMN_ID;\n    case TITLE = \\PSX\\Sql\\Tests\\Generator\\SqlTableTestTable::COLUMN_TITLE;\n    case DATE = \\PSX\\Sql\\Tests\\Generator\\SqlTableTestTable::COLUMN_DATE;\n}\n```\n","funding_links":["https://github.com/sponsors/chriskapp","https://patreon.com/fusio","https://www.paypal.me/fusioapi"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapioo%2Fpsx-sql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapioo%2Fpsx-sql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapioo%2Fpsx-sql/lists"}