# 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');
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.siteadministrator.com/developer-guide/models-and-doctrine-orm/repositories.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
