PHPackages                             vespolina/molino - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. vespolina/molino

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

vespolina/molino
================

Small and fast library to make reusable tools persistence backend agnostic.

76.4k1PHP

Since Dec 25Pushed 12y ago2 watchersCompare

[ Source](https://github.com/vespolina/molino)[ Packagist](https://packagist.org/packages/vespolina/molino)[ RSS](/packages/vespolina-molino/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (1)

Molino
======

[](#molino)

[![Build Status](https://camo.githubusercontent.com/377c220c615d213978ea6d3eeff197d24b8ad2139a96697d9820608966522956/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f7061626c6f6469702f6d6f6c696e6f2e706e67)](http://travis-ci.org/pablodip/molino)

Molino is a small and fast library to make reusable tools persistence backend agnostic.

Molino doesn't provide anything for defining models. This means that you have to define the models for the backend you want to work with in a normal way.

Usage
-----

[](#usage)

You work with a molino, which is just an implementation of the `MolinoInterface`:

```
$molino = new Molino();

```

### Name

[](#name)

Each molino must have a name:

```
$name = $molino->getName();

```

### Creating models

[](#creating-models)

You can create models by using the `createModel` method with the model class as the first argument:

```
$article = $molino->create('Model\Article');

```

### Setting and getting data

[](#setting-and-getting-data)

As using setters and getters is a convention nowadays, Molino doesn't include any method to abstract this. So that you can use setters and getters in a normal way with the models:

```
$article->setTitle('foo');
$title = $article->getTitle();

```

### Saving models

[](#saving-models)

You can save models by using the `saveModel` method:

```
$molino->save($article);

```

### Refreshing models

[](#refreshing-models)

You can refresh models by using the `refreshModel` method:

```
$molino->refresh($article);

```

### Deleting models

[](#deleting-models)

You can delete models by using the `deleteModel` method:

```
$molino->delete($article);

```

Querying
--------

[](#querying)

Molino has three types of queries: select, update and delete, which you can create from the molino:

```
$selectQuery = $molino->createSelectQuery('Model\Article');
$updateQuery = $molino->createUpdateQuery('Model\Article');
$deleteQuery = $molino->createDeleteQuery('Model\Article');

```

### Molino and model class

[](#molino-and-model-class)

You can access to the molino and model class from all queries:

```
$molino = $query->getMolino();
$modelClass = $query->getModelClass();

```

### Filtering

[](#filtering)

The three types of queries can be filtered:

```
$query->filterEqual('name', 'Pablo');
$query->filterNotEqual('name', 'Pablo');

$query->filterLike('name', 'Pablo*');
$query->filterNotLike('name', '*Pablo');

$query->filterIn('name', array('Pablo', 'Pepe'));
$query->filterNotIn('name', array('Pablo', 'Pepe'));

$query->filterGreater('age', 20);
$query->filterLess('age', 20);
$query->filterGreaterEqual('age', 20);
$query->filterLessEqual('age', 20);

```

You can also use the `filter` method, which links to those methods:

```
$query->filter('name', '==', 'Pablo');
$query->filter('name', '!=', 'Pablo');

$query->filter('name', 'in', array('Pablo', 'Pepe'));
$query->filter('name', 'not_in', array('Pablo', 'Pepe'));

$query->filter('age', '>', 20);
$query->filter('age', '=, 20);
$query->filter('age', 'select(array('title', 'content'));

```

You can sort, limit, skip:

```
$selectQuery->sort('name', 'asc'); // asc o desc
$selectQuery->limit(10);
$selectQuery->skip(10);

```

You can retrieve all, one and the number of results:

```
$articles = $selectQuery->all();
$article = $selectQuery->one();
$nbArticles = $selectQuery->count();

```

Select queries implement both the `Countable` and `IteratorAggregate` interfaces:

```
$nb = count($selectQuery);
foreach ($selectQuery as $model) {
    // ...
}

```

Select queries allow you to create an adapter for [Pagerfanta](https://github.com/whiteoctober/Pagerfanta):

```
use Pagerfanta\Pagerfanta;

$adapter = $selectQuery->createPagerfantaAdapter();
$pagerfanta = new Pagerfanta($adapter);

```

### Updating

[](#updating)

You can set and increment fields:

```
$updateQuery->set('name', 'Pablo');
$updateQuery->inc('age', 1);

```

Then you execute the update queries:

```
$updateQuery->execute();

```

### Removing

[](#removing)

Remove queries can only be filtered and executed:

```
$removeQuery->execute();

```

### Fluent interface

[](#fluent-interface)

All queries implement a fluent interface:

```
$articles = $molino->createSelectQuery('Model\Article')
    ->filterEqual('isActive', true)
    ->sort('createdAt', 'desc')
    ->limit(10)
    ->all()
;

```

Molinos
-------

[](#molinos)

Molino comes with four molinos:

### Mandango

[](#mandango)

To work with [Mandango](http://mandango.org/):

```
use Molino\Mandango\Molino;

$molino = new Molino($mandango);
$molino->getName() // mandango

```

### Doctrine ORM

[](#doctrine-orm)

To work with [Doctrine ORM](http://www.doctrine-project.org/projects/orm):

```
use Molino\Doctrine\ORM\Molino;

$molino = new Molino($entityManager);
$molino->getName() // doctrine_orm

```

### Doctrine MongoDB ODM

[](#doctrine-mongodb-odm)

To work with [Doctrine MongoDB ODM](http://www.doctrine-project.org/projects/mongodb-odm.html):

```
use Molino\Doctrine\ODM\MongoDB\Molino;

$molino = new Molino($documentManager);
$molino->getName() // doctrine_mongodb_odm

```

### Memory

[](#memory)

To be used for testing. It requires no mapping or access a database:

```
use Molino\Memory\Molino;

$molino = new Molino();
$molino->getName() // memory

```

Events
------

[](#events)

You can optionally use events with molinos. In order to do that you have to use the class `EventMolino`, which receives a molino and an event dispatcher. You can use the event molino in a normal way, as it also implements the `MolinoInterface` it simply wraps a molino for use with events.

`EventMolino` depends on the Symfony2 EventDispatcher component, since it must receive an instance of `Symfony\Component\EventDispatcher\EventDispatcherInterface` as event dispatcher.

```
use Molino\Mandango\Molino;
use Molino\EventMolino;
use Symfony\Component\EventDispatcher\EventDispatcher;

$eventDispatcher = new EventDispatcher();
$mandangoMolino = new Molino($mandango);
$molino = new EventMolino($mandangoMolino, $eventDispatcher);

// using the final molino in a normal way
$model = $molino->createSelectQuery('Model\Article')
    ->filterEqual('is_active', true)
    ->sort('created_at', 'desc')
    ->one()
;

```

### Event classes

[](#event-classes)

There are two event classes used:

- `Molino\Event\ModelEvent`: for events with a model.
- `Molino\Event\QueryEvent`: for events with a query.

You can access to the molino in both classes:

```
$molino = $modelEvent->getMolino();
$molino = $queryEvent->getMolino();

```

And to the model or query depending on the class:

```
$model = $modelEvent->getModel();
$modelEvent->setModel($model);

$query = $queryEvent->getQuery();
$queryEvent->setQuery($query);

```

### Events

[](#events-1)

The events you can use are saved as constants in the class `Molino\Event\Events`. They are:

- `CREATE`: when creating a model. It uses a `ModelEvent`.
- `PRE_SAVE`: before saving a model. It uses a `ModelEvent`.
- `POST_SAVE`: after saving a model. It uses a `ModelEvent`.
- `PRE_REFRESH`: before refreshing a model. It uses a `ModelEvent`.
- `POST_REFRESH`: after refreshing a model. It uses a `ModelEvent`.
- `PRE_DELETE`: before deleting a model. It uses a `ModelEvent`.
- `POST_DELETE`: after deleting a model. It uses a `ModelEvent`.
- `CREATE_QUERY`: when creating any query (select, update, delete). It uses a `QueryEvent`.

### Examples

[](#examples)

Assigning an author to the articles automatically when creating articles:

```
use Molino\Event\Events;
use Molino\Event\ModelEvent;
use Model\Article;

$author = get_author();

$eventDispather->addListener(Events::CREATE, function (ModelEvent $event) use ($author) {
    if ($event->getModel() instanceof Article) {
        $event->getModel()->setAuthor($author);
    }
});

```

Filtering all articles queries by an author:

```
use Molino\Event\Events;
use Molino\Event\QueryEvent;

$author = get_author();

$eventDispather->addListener(Events::CREATE_QUERY, function (QueryEvent $event) use ($author) {
    if ('Model\Article' === $event->getQuery()->getModelClass()) {
        $event->getQuery()->filterEqual('author_id', $author->getId());
    }
});

```

Limitations
-----------

[](#limitations)

You can do many things with Molino, but as you can probably guess you can't do everything as its API is small (though it's like this to be compatible with different backends).

Anyway, this doesn't mean you can't do complex things compatible with different backends. You just need to implement the parts you can't do with Molino directly by discriminating by backend:

```
if ('mandango' === $molino->getName()) {
    // Mandango implementation
} elseif ('doctrine_orm' === $molino->getName()) {
    // Doctrine ORM implementation
} else {
    throw new \RuntimeException('This application only works with the following molinos: "mandango", "doctrine_orm".');
}

```

Author
------

[](#author)

Pablo Díez -

License
-------

[](#license)

Molino is licensed under the MIT License. See the LICENSE file for full details.

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity23

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 83.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/c36892b0d7889179d04c8c39e6fb84b57ff16656d34737e8f6350cb0ed01ea28?d=identicon)[inspiran](/maintainers/inspiran)

---

Top Contributors

[![pablodip](https://avatars.githubusercontent.com/u/98504?v=4)](https://github.com/pablodip "pablodip (25 commits)")[![inspiran](https://avatars.githubusercontent.com/u/372447?v=4)](https://github.com/inspiran "inspiran (3 commits)")[![cordoval](https://avatars.githubusercontent.com/u/328359?v=4)](https://github.com/cordoval "cordoval (1 commits)")[![richsage](https://avatars.githubusercontent.com/u/231551?v=4)](https://github.com/richsage "richsage (1 commits)")

### Embed Badge

![Health badge](/badges/vespolina-molino/health.svg)

```
[![Health](https://phpackages.com/badges/vespolina-molino/health.svg)](https://phpackages.com/packages/vespolina-molino)
```

###  Alternatives

[asgardcms/menu-module

Menu module for AsgardCMS. Handles all the menus.

1030.4k2](/packages/asgardcms-menu-module)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
