---
# System prepended metadata

title: Factories y Repositories

---

# Factories y Repositories

En Goteo tenemos una aplicación PHP basada en el patron MVC (Modelo, Vista, Controlador), dado que es una aplicación Symfony.

Dentro de Goteo podemos encontrar zonas de nuestro dominio, en el qual, se debe visualizar un listado de Proyectos, Canales, etc. Para esto normalmente tenemos una función dentro del modelo que nos permite obtener un listado de los objectos que cumplen las condiciones.

```php
public class Project extends \Goteo\Core\Model {

    public function getList($filters = [], $offset, $limit, $count = false);
}
``` 

Cada modelo se responsabiliza de generar las funciones necesarias para poder extraer los listados que se pueden utilizar en las diferentes capas de la aplicación.

Así podemos encontrar zonas donde se puedan listar todos los proyectos:

```php
$total = Project::getList(['node' = 'goteo'], 0, 0, true)
$projects = Project::getList(['node' = 'goteo'], 0, $total);
```

De esta manera obtendríamos todos los proyectos relacionados con el nodo Goteo.

También podemos encontrar listado de los proyectos financiados en los últimos X meses.

```php
    public static function getFunded($months = 10) {
```

De la manera en la que hemos estado trabajando, estamos dotando al modelo de toda la responsabilidad de la gestión de los datos con la BBDD y de toda la manipulación de los datos para los controladores.

Con esta forma de trabajar hemos acabado con modelos que contienen hasta 3677 línias de código (Project.php), cerca de 2500 (Invest.php) u otros.

Por otra parte, encontramos que en determinados casos de uso, se necesita crear nuevas entidades que queden guardadas en nuestra Base de Datos. 

- Un usuario nuevo
- Una donación (por paypal, por tpv, por monedero, etc)
- Un certificado de donacion
- Un proyecto (Un proyecto en un canal, en un matcher, etc)

Actualmente, los controladores se deben encargar de gestionar que los nuevos objetos creados contengan toda la información correcta y se relacionen correctamente entre objectos antes de guardarlos, p.ej. el proyecto tiene un usuario vinculado, la donación también, etc.

## Factory

Para solucionar este último problema, podríamos comenzar a desarrollar clases con el funcionamiento de Fábricas. De estas clases obtendriamos funciones para poder crear correctamente cada objeto, en función de la situación en la que nos encontramos.

## Repository

Para la obtención de la información de los diferentes modelos en las diferentes circumstancias, podríamos plantearnos utilizar Repositorios.

Estos nos darían las funciones necesarias para poder obtener, en los controladores que hagan falta, ciertos listados con las especificades necesarios.

Un ProjectRepository podría albergar todas las funciones que contiene la clase Project y que nos permiten obtener listados y filtrado de las entradas.

De esta manera podríamos tener un código más modular, más fácil de mantener.


## Referencias

[How to Create custom Repository Classes](https://symfony.com/index.php/doc/3.4/doctrine/repository.html)

[Using a Factory to Create Services](https://symfony.com/doc/current/service_container/factories.html)

[Factory Method in PHP](https://refactoring.guru/design-patterns/factory-method/php/example)

