# Repositories

The repository design pattern is an abstraction over the storage of a specific [model](https://app.gitbook.com/s/-LB7PTje97ARlss-zn8u/developer-guide/models-and-doctrine-orm/models.md). In other words, they represent a collection of an entity (aka model). Repositories hold the logic for retrieving and filtering results from the collection. They **do not** represent database storage or any other form of persistence logic.

In practice, repositories are commonly home to methods like `find()`, `findOneBy()`, `findActiveUsers()`, `findUserWithUsernameAndPassword()`. Notice these methods imply retrieving or filtering a collection of data. These methods do not create, update, or delete data. Nor do they reveal the technology being used to persist the data (i.e database, in-memory, etc.).

SiteAdmin modules use the repository design pattern to access models which have been persisted to storage. They are directly mapped to a single model, and are used to query only that model.

## Creating a Repository

### The Repository Class

```php
<?php
use sa\application\DefaultRepository;
​
class CompaniesRepository extends DefaultRepository
{
    // <implement querying methods>
}
```

#### Default Methods

The `DefaultRepository` class offers a few common repository operations, so you can dive into using your repository without writing boilerplate code.

| Method                                                                                                          | Description                                      |
| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| find(`$id`)                                                                                                     | Finds an entity by its primary key / identifier. |
| findAll()                                                                                                       | Finds all entities in the repository.            |
| findBy(`array` ​orderBy = null, ​offset = null)                                                               | Finds entities by a set of criteria.             |
| findOneBy(`array` ​orderBy\` = null)                                                                          | Finds a single entity by a set of criteria.      |
| search(`array` ​orderBy, ​offset = null, ​secondary\_sort = null, ​search\_start = true, $search\_end = true) | Finds entities by a set of complex criteria.     |

#### Custom Repository methods

You'll likely need to create custom search queries for your model(s). For this, we use the [Doctrine ORM query builder](http://docs.doctrine-project.org/en/latest/reference/query-builder.html).

```php
<?php
use sa\application\DefaultRepository;
​
class CompaniesRepository extends DefaultRepository
{
    public function findCompaniesByName($searchTerm) {
        $qb = $this->createQueryBuilder('c');
        $qb->where($qb->expr()->like('LOWER(c.name)', ':name'))
            ->setParameter('name', '%' . strtolower(trim($searchTerm)) . '%');
​
​
        return $qb->getQuery()->getResult();
    }
}
```

### Mapping Repository to Model

Each repository must be mapped to a [model](https://app.gitbook.com/s/-LB7PTje97ARlss-zn8u/developer-guide/models-and-doctrine-orm/models.md). This is achieved by adding the repository's namespace to a model's `@Entity` annotation.

> Notice the repository class simply reads `CompanyRepository`. This is acceptable because both the `Company` and `CompanyRepository` classes reside in the same namespace. If they were in different namespaces, the annotation would instead read:
>
> ```php
> @Entity(repositoryClass="\other\namespace\CompanyRepository")
> ```

**/modules/Companies/models/Company**

```php
<?php
/**
 * @Entity(repositoryClass="CompanyRepository")
 */
class Company {
    // <properties, getters/setters, helper methods>
}
```

## Using a Repository

### Access from Entity Manager

> **Deprecation Notice**Accessing repositories directly from the entity manager is deprecated. Use the IOC manager to access repositories instead.

You can get the instance of a repository via doctrine's entity manager. Because modules are often extended, you should use `ioc::resolve('{entityName}')` instead of hard-coding a model's namespace. This will allow the application to use the repositories mapped to extended models.

```php
<?php
$companyRepository = app::$entityManager->getRepository(ioc::resolve('Company'));
```

### Access from IOC

The [IOC manager](https://app.gitbook.com/s/-LB7PTje97ARlss-zn8u/developer-guide/models-and-doctrine-orm/ioc.md) offers a simplified interface compared to the entity manager's `getRepository()` method, which requires manually resolving a model's IOC reference.

```php
<?php
$companyRepository = ioc::getRepository('Company');
```
