{"id":16616524,"url":"https://github.com/parable-php/orm","last_synced_at":"2025-10-29T19:30:49.317Z","repository":{"id":57035810,"uuid":"174686043","full_name":"parable-php/orm","owner":"parable-php","description":"Parable ORM is a light-weight repository-pattern based ORM.","archived":false,"fork":false,"pushed_at":"2021-03-12T15:24:26.000Z","size":130,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-02T04:31:44.670Z","etag":null,"topics":["database","library","orm","parable","php8","repository"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/parable-php.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-09T11:32:48.000Z","updated_at":"2021-03-12T15:24:30.000Z","dependencies_parsed_at":"2022-08-23T20:50:41.853Z","dependency_job_id":null,"html_url":"https://github.com/parable-php/orm","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parable-php%2Form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parable-php%2Form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parable-php%2Form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parable-php%2Form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/parable-php","download_url":"https://codeload.github.com/parable-php/orm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238874462,"owners_count":19545195,"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","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","library","orm","parable","php8","repository"],"created_at":"2024-10-12T02:13:22.161Z","updated_at":"2025-10-29T19:30:44.023Z","avatar_url":"https://github.com/parable-php.png","language":"PHP","readme":"# Parable ORM\n\n[![Workflow Status](https://github.com/parable-php/orm/workflows/Tests/badge.svg)](https://github.com/parable-php/orm/actions?query=workflow%3ATests)\n[![Latest Stable Version](https://poser.pugx.org/parable-php/orm/v/stable)](https://packagist.org/packages/parable-php/orm)\n[![Latest Unstable Version](https://poser.pugx.org/parable-php/orm/v/unstable)](https://packagist.org/packages/parable-php/orm)\n[![License](https://poser.pugx.org/parable-php/orm/license)](https://packagist.org/packages/parable-php/orm)\n\nParable ORM is a light-weight repository-pattern based ORM.\n\n## Install\n\nPhp 8.0+ and [composer](https://getcomposer.org) are required.\n\n```bash\n$ composer require parable-php/orm\n```\n\n## Usage\n\nRepositories are used to find, save and delete entities, which represent rows from your MySQL/Sqlite database. Parable ORM attempts to combine queries to be as efficient as possible.\n\nEntities are relatively straight-forward PHP data objects, and are expected to offer setters and getters for all values associated with that entity. Example:\n\n```php\nclass Entity extends AbstractEntity {\n    protected $id;\n    protected $name;\n\n    // We int cast because we know it is an int\n    public function getId(): int {\n        return (int)$this-\u003eid;\n    }\n\n    public function setName(string $name): void {\n        $this-\u003ename = $name;\n    }\n\n    public function getName(): ?string {\n        return $this-\u003ename;\n    }\n}\n```\n\nAs you can see, the entity itself doesn't really need much. The Repository set up for this entity type, however, will contain some metadata so it knows how to handle them.\n\nIf you want to support automatic setting of a `created at` or `updated at` value, it's as simple as implementing either the `SupportsCreatedAt` or `SupportsUpdatedAt` interfaces. The repository will automatically pick up on it and attempt to call `markCreatedAt()` or `markUpdatedAt()`, leaving the specific property/column names up to you. Example:\n\n```php\nclass Entity extends AbstractEntity implements SupportsCreatedAt {\n    protected $id;\n    protected $created_at;\n\n    // We int cast because we know it is an int\n    public function getId(): int {\n        return (int)$this-\u003eid;\n    }\n\n    public function getCreatedAt(): ?string {\n        return $this-\u003ecreated_at;\n    }\n\n    public function setCreatedAt(string $createdAt): void {\n        $this-\u003ecreated_at = $createdAt;\n    }\n\n    // Only this method is defined on the interface\n    public function markCreatedAt(): void {\n        $this-\u003esetCreatedAt((new DateTimeImmutable())-\u003eformat(Database::DATETIME_SQL));\n    }\n}\n```\n\nHere's the Repository to handle the above Entity:\n\n```php\nclass EntityRepository extends AbstractRepository {\n    public function getTableName(): string {\n        return 'entity';\n    }\n\n    public function getPrimaryKey(): string {\n        return 'id';\n    }\n\n    public function getEntityClass(): string {\n        return Entity::class;\n    }\n}\n```\n\nAs mentioned, both entities and repositories are intended to be as simple and straightforward as possible. Entities and Repositories use `parable-php/di`, meaning they can use constructor-based injected dependencies.\n\n#### Basic Repository use\n\n```php\n$repository-\u003efindAll(); // returns AbstractEntity[]\n```\n```php\n$repository-\u003ecountAll(); // returns int\n```\n```php\n$repository-\u003efind(23); // returns ?AbstractEntity\n```\n\n#### Condition-based repository use\n\nFor advanced (and possibly complex) where conditions, we use a `callable` which is given a properly set up `Query` object. This allows for fine-grained control with a very low barrier to do so.\n\n```php\n$repository-\u003efindBy(function (Query $query) {\n    $query-\u003ewhere('name', '=', 'First-name');\n    $query-\u003ewhereNotNull('activated_at');\n    $query-\u003ewhereCallable(function (Query $query) {\n        $query-\u003ewhere('test_value', '=', '1');\n        $query-\u003eorWhere('test_value', '=', '4');\n    });\n});\n```\n\nThis ends up building the following query:\n\n```sql\nSELECT * FROM `entity` \nWHERE (\n    `entity`.`name` = 'First-name' \n    AND `entity`.`activated_at` IS NOT NULL \n    AND (\n        `entity`.`test_value` = '1' \n        OR `entity`.`test_value` = '4'\n    )\n);\n```\n\nThe methods `where`, `whereNull`, `whereNotNull` and `whereCallable` will use `AND` to combine the clauses. To do otherwise, all have an `or`-version. `orWhere`, `orWhereNull`, `orWhereNotNull`, `orWhereCallable`, and by using those specifically, an `OR` clause can be created.\n\nIn many cases you'll want to either only use `or`-clauses, or, to use an `OR` clause in an otherwise `AND`-oriented where list, use a `callable` to make sure they're grouped appropriately.\n\n#### Saving and deleting entities\n\nTo save an entity, simply tell the repository to do so:\n```php\n$savedEntity = $repository-\u003esave($entity);\n```\n\nOr save multiple:\n```php\n$savedEntities = $repository-\u003esaveAll($entity1, $entity2, $entity3);\n```\n\nYou can also easily defer a save, so that the entity is prepared for a save but not actually saved until you decide to do so. When this is done, all entities that need to be updated are saved individually as they are found in the deferred save list, but all entities that are new (aka to be `INSERT`ed) are combined into a single `INSERT` query instead.\n\n```php\nforeach ($newEntities as $entity) {\n    $repository-\u003edeferSave($entity);\n}\n// OR:\n$repository-\u003edeferSave(...$newEntities);\n\n$repository-\u003esaveDeferred(); // returns nothing\n```\n\nIf `$newEntities` contains 10 entities that are all new, one query will now insert all 10 in one go. If, for example, `$newEntities` contains 5 new and 5 pre-existing entities, `saveDeferred` will build the single `INSERT` query for the 5 new ones, and as it comes across them, save the updates immediately.\n\nDeleting works the same:\n```php\n$repository-\u003edelete($entity); // Single\n$repository-\u003edelete($entity1, $entity2); // Multiple, just keep adding\n$repository-\u003edelete(...$entities); // Splats for the win\n```\n\nAnd deferred deletes are also possible, and will attempt to delete all deferred entities in a single query:\n\n```php\n$repository-\u003edeferDelete($entity); // Single\n$repository-\u003edeferDelete($entity1, $entity2); // Multiple, just keep adding\n$repository-\u003edeferDelete(...$entities); // Splats for the win\n\n$repository-\u003edeleteDeferred(); // Actually perform it.\n```\n\nFor both deferred saves and deletes, the currently stored entities to be saved or deleted can be cleared by calling either `clearDeferredSaves()` or `clearDeferredDeletes()`.\n\n#### How to connect to a database\n\nYou didn't think I'd ever forget this, do you? 2 database types are currently supported, MySQL and Sqlite3.\n\nTo connect to a MySQL server:\n\n```php\n$database = new Database(\n    Database::TYPE_MYSQL, \n    'parable',\n    'localhost',\n    'username',\n    'password'\n);\n```\n\nOr:\n\n```php\n$database = new Database();\n$database-\u003esetDatabaseName('parable');\n$database-\u003esetHost('localhost');\n$database-\u003esetUsername('username');\n$database-\u003esetPassword('password');\n\n$database-\u003econnect();\n\n$results = $database-\u003equery('SELECT * FROM users');\n```\n\nAnd to connect to a Sqlite3 file:\n\n```php\n$database = new Database(\n    Database::TYPE_SQLITE, \n    'storage/parable.db'\n);\n```\n\nOr:\n\n```php\n$database = new Database();\n$database-\u003esetDatabaseName('storage/parable.db');\n\n$database-\u003econnect();\n\n$results = $database-\u003equery('SELECT * FROM users');\n```\n\n## Contributing\n\nAny suggestions, bug reports or general feedback is welcome. Use github issues and pull requests, or find me over at [devvoh.com](https://devvoh.com).\n\n## License\n\nAll Parable components are open-source software, licensed under the MIT license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparable-php%2Form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparable-php%2Form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparable-php%2Form/lists"}