Entity repository

The repository wraps all database interactions and provides a convenient way to get multiple entities from the database.

Internally it uses the Query builder to interact with the database. The repository exposes a lot of methods from the Query builder. So make sure you check out the Query builder documentation to see what's possible.

Basic usage

To create a new instance of the repository you can use a factory method directly from the entity or create a new instance yourself. In the latter case you need to provide the repository with the entity class name you are working with.

// You can use the factory method on a entity to conveniently create a new repository instance
$repository = user::repository();
// Or instantiate the repository directly
$repository = new \core\orm\entity\repository(user::class);

create_entity(), save_entity(), update_entity(), delete_entity() / refresh_entity()

These methods can also be triggered from the entity directly but they essentially just forward to the repository method.

$user = new user([
    'firstname' => 'Bob',
    'lastname' => 'Jones'
]);

// Only the repository takes care of interactions with the query builder and database layer
// The save method of the entity for example is just a shortcut to the repository
user::repository()->create_entity($user);
// or call save as it handles create() and update() automatically
user::repository()->save_entity($user);
// to delete an entity
user::repository()->delete_entity($user);
// to delete an entity 
user::repository()->refresh_entity($user)

get()

get() is probably the most important method and gives you a lot of flexibility as it allows to use the Query builder methods to filter for entities.

It returns a collection of entities. The collection implements the Iterator interface so you can use foreach() for example to go through the result. It also gives you some nice methods for working with it. See Collection for more information.

// just get all entities from the table
$users = user::repository()->get();

// You can use more complex "queries"
$users = user::repository()
    ->where('firstname', 'Bob')
    ->get();

foreach ($users as $user) {
    echo $user->lastname;
}

Pagination

Very often you don't want to get all records in a table at once but you have a pagination in place. The paginate() method helps you with that. It returns a paginator object containing information about your pagination and your collection of items.

In combination with filters and sorting you can achieve quite a lot.

See the Paginator documentation for more details.

// paginates accepts a page number starting with 1, 
// and a second per_page argument to influence the number of entities per page
$users = user::repository()->paginate(2, 20);

// It returns a paginator result which wraps the collection
// and contains meta data about your pagination
print_r($users->to_array());

// Array(
//     'items' => Array(
//         Array(
//             'id' => 1,
//             'firstname' => 'Bob',
//             'lastname' => 'Jones'
//         ),
//         ...
//     ),
//     'page' => 2,   // current page you are on
//     'pages' => 5,  // total number of pages
//     'per_page' => 20,  
//     'next' => 3,   // next page number, null on the last page
//     'prev' => 1,   // previous page number, null on the first page
//     'total' => 98  // total number of items
// )

Collection

The collection class provides a few convenient methods you can use.

Check out the Collection documentation for details.

Lazy collection

If you need to load a lot of records/results from the database and need a memory saving way you can use the lazy_collection. The lazy_collection internally uses the DML record-set. It is very restricted in functionality. You can only loop over the records/entities.

$users = user::repository()->get_lazy();
foreach ($users as $user) {
    // if you use the repository you get entity instances
    print_r($user->to_array());
}

$users = builder::create_for('user')->get_lazy(); 
foreach ($users as $user) {
    // if you use the builder you get arrays
	print_r($user);
}

Specific repository

If you just have your entity class a call to my_entity::repository() gives you the generic repository() instance.

Sometimes you want to have entity-specific reusable functionality. In this case you can create your specific repository. It needs to be in the same namespace and has to have the same class name as the entity suffixed with _repository. There you can create your own repository methods.

/**
 * You may want to type-hint your specific history for autocompletion in your IDE
 * 
 * @method static user_repository repository()
 */
class user extends \core\orm\entity\entity {
    
    protected $table = 'user';

}

class user_repository extends \core\orm\entity\repository {

    /**
     * Filter by firstname or lastname
     *
     * @param string $name
     * @return $this
     */
    public function filter_by_name($name) {
        // an example of a nested where condition, essentialy (firstname = ? OR lastname = ?)
        $this->builder->where(function (builder $builder) {
            $builder->where('firstname', $name)
                ->or_where('lastname', $name);
        });

        return $this;
    }

}

// Get all users with firstname or lastname = Max
$user = user::repository()
    ->filter_by_name('Max')
    ->get();

Customise repository name

If you don't want to follow the default convention and have a custom repository class located in the same folder and named as entity_repository, you may override this handy dandy static entity method repository_class_name which must return a class name for your custom repository. Next time you call entity::repository() it will return an instance of the custom class you specified. Please note, it must extend the \core\orm\entity\repository class.