A modular database abstraction system, focused on performance and usability
Well, yes, I agree that there are far too many DB abstraction libraries available for PHP, I have use many of them myself. The problem I always found was that they seemed to be more concerned with adding more features and being able to do everything instead of what I wanted; an easy-to-use API which could be used in situations which require high performance.
I'm a PHP developer. I want to deal with objects and PHP code and any libraries I use have to be fast and efficient. I don't want to have to learn another query language, be writing annotations everywhere (don't get me started) or using systems that run out of memory trying to process 10,000 records.
Reposition is designed to be lean and quick, both when writing for it and when running it. It takes care of almost all of the grudwork, letting you focus on developing your application rather than wrestling with queries or worrying about the performance cost of loading all those records. Even complex entity relationships are handled with ease, the only requirement being that you know beforehand what information you want to load or save.
In addition to this, Reposition is modular. The API is designed to be database agnostic, meaning you can change your database provider without having to change any of your repositories or models. Reposition was originally written for a NoSQL database and later refactored for use with SQL, so it is even possible to swap between these two types of database (although the data schema for each type is likely to be incompatible). The point is, you have flexibility and choice with as few constraints as possible.
Typically, you don't install reposition directly; it is a requirement of the module for your chosen database provider. However, if you want to create a module, you can install via composer:
composer require lexide/reposition
or
{
"require": {
"lexide/reposition": "^1.0"
}
}
Reposition modules use the "single responsibility" ethos; a module should do one thing and do it well. There are currently two modules for Reposition:
Reposition SQL is, as it's name suggests, a module that enables SQL databases to be used with Reposition. It performs queries on a database, using a sequence of tokens that are generated by the repository classes. It has been tested with MySQL and PostgreSQL and should be fairly easy to adapt to other flavours of SQL database.
Reposition Clay manages the entities that are used in each repository. It generates the entity metadata that each repository uses to create queries with and also creates entities from the raw query returned from a query. "Clay" is the name of the model creation library that it uses.
In most cases you will want to include both modules in any project that uses Reposition. However, you are free to use any solution that replicates the functionality of each part, or to write your own if you prefer.
This is an example of a Reposition repository
use Lexide\Reposition\Repository\AbstractRepository;
class ExampleRepository extends AbstractRepository
{
protected $collectionName = "example_table"
}
... yeah, thats right. Thats all you need. With this, you can find, filter, save and delete entities without any further modification to the repository class.
More complex queries can be written by creating new methods on the repository class and using the query builder to create the custom query. Relationships between entities can be defined by overriding the configureMetadata method and adding the required configuration.
Four objects are required when creating a new repository: Entity Metadata is needed to give the repository information about the entity it is interacting with, the Query Builder allows the repository to create sequences of tokens that represent a database query, the Storage object provides access to the database implementation and the Metadata Provider allows the repository to access metadata on related entities (to create joins when loading or to cascade update operations when saving, for example)
Fortunately, the RepositoryManager exists to make this process as seamless as possible. The following code will create a repository for a particular entity:
$repository = $repositoryManager->getRepositoryFor($entityOrEntityClassName);
The repository manager can be created manually, or configured via dependency injection. The repositories themselves can be dependency injected by any DI library that can use factory services. The following is an example for the Syringe DI library:
repository:
class: RepositoryClassName
factoryService: "@repositoryManager"
factoryMethod: "getRepositoryFor"
arguments:
- EntityClassName
More in-depth documentation can be found at readthedocs.org. Please note this is a work in progress.
Written by Danny Smart (Downsider) and Silktide Ltd