PHPackages                             bentools/opencubes - 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. bentools/opencubes

ActiveLibrary

bentools/opencubes
==================

0.1.1(7y ago)1487MITPHPPHP ^7.1.3CI failing

Since Feb 22Pushed 5y ago1 watchersCompare

[ Source](https://github.com/bpolaszek/opencubes)[ Packagist](https://packagist.org/packages/bentools/opencubes)[ RSS](/packages/bentools-opencubes/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (10)Versions (5)Used By (0)

[![Latest Stable Version](https://camo.githubusercontent.com/a0f4263f0f55bd30c08132f78629b14ee7681a7582d11029c788dc3923031bab/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f6f70656e63756265732f762f737461626c65)](https://packagist.org/packages/bentools/opencubes)[![License](https://camo.githubusercontent.com/4694e3ec605c48823db7c96a5fe296b13076dd16d853fe7352595dbaae34aaa6/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f6f70656e63756265732f6c6963656e7365)](https://packagist.org/packages/bentools/opencubes)[![Build Status](https://camo.githubusercontent.com/c244431b97e3a63963434fbb176724fcba81014856f986468f85c0af3f7761f9/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f62706f6c61737a656b2f6f70656e63756265732f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/bpolaszek/opencubes)[![Coverage Status](https://camo.githubusercontent.com/90b902743b990989ade94266e6cf73a691e385ea9119285ae0353669affdd040/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f62706f6c61737a656b2f6f70656e63756265732f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/bpolaszek/opencubes?branch=master)[![Quality Score](https://camo.githubusercontent.com/6a7c30adea432fc34c06dfbcfb520ba6e45f4473ef45243742702d048b5ab27d/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f62706f6c61737a656b2f6f70656e63756265732e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/bpolaszek/opencubes)[![Total Downloads](https://camo.githubusercontent.com/525c25e9466b69627e7d79062d63bd154fe7f19b1dde1d553634a1827b2b75b5/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f6f70656e63756265732f646f776e6c6f616473)](https://packagist.org/packages/bentools/opencubes)

OpenCubes
=========

[](#opencubes)

**OpenCubes** is a framework-agnostic set of components that parses PSR-7 URIs into value objects:

- Pagination
- Filters
- Sorting
- Breakdown (group by)

Overview
--------

[](#overview)

Look at the following URL:

> [https://your.application/books?page=3&amp;per\_page=50&amp;sort\[author.name\]=asc&amp;filters\[published\_at\]=\[2019-01-01+TO+2019-01-31\]&amp;filters\[category\_id\]=12&amp;filters\[tags\]\[\]=foo&amp;filters\[tags\]\[\]=bar&amp;filters\[name\]\[NOT\]\[STARTS\_WITH\]=foo](https://your.application/books?page=3&per_page=50&sort%5Bauthor.name%5D=asc&filters%5Bpublished_at%5D=%5B2019-01-01+TO+2019-01-31%5D&filters%5Bcategory_id%5D=12&filters%5Btags%5D%5B%5D=foo&filters%5Btags%5D%5B%5D=bar&filters%5Bname%5D%5BNOT%5D%5BSTARTS_WITH%5D=foo)

Here's how OpenCubes parses it:

```
use BenTools\OpenCubes\Component\Filter\FilterComponent;
use BenTools\OpenCubes\Component\Sort\SortComponent;
use BenTools\OpenCubes\Component\Pager\PagerComponent;
use BenTools\OpenCubes\Component\Filter\Model\CollectionFilter;
use BenTools\OpenCubes\Component\Filter\Model\RangeFilter;
use BenTools\OpenCubes\Component\Filter\Model\SimpleFilter;
use BenTools\OpenCubes\Component\Filter\Model\StringMatchFilter;
use BenTools\OpenCubes\OpenCubes;
use function BenTools\OpenCubes\current_location;

$openCubes = OpenCubes::create();
$sorting = $openCubes->getComponent(SortComponent::getName());
$filters = $openCubes->getComponent(FilterComponent::getName());
$pager = $openCubes->getComponent(
    PagerComponent::getName(),
    ['default_size' => 100],
    current_location() // current_location() is the default and can be replaced by any PSR-7 Uri object
);

// Pagination
echo $pager->getCurrentPage(); // 3
echo $pager->getPerPage(); // 50 (it would be 100 when omiting the per_page parameter)
echo $pager->getCurrentOffset(); // 100

$pager->setNbItems(160); // Your application found 160 items
echo count($pager); // 4 pages of 50 for 160 items

// Sorting
foreach ($sorting->getAppliedSorts() as $sort) {
    echo $sort->getField(); // author.name
    echo $sort->getDirection(); // asc
}

// Filters
foreach ($filters->getAppliedFilters() as $filter) {

    if ($filter instanceof RangeFilter) {
        echo $filter->getField(); // published_at
        echo $filter->getLeft(); // 2019-01-01
        echo $filter->getRight(); // 2019-01-31
    }

    if ($filter instanceof SimpleFilter) {
        echo $filter->getField(); // category_id
        echo $filter->getValue(); // 12
    }

    if ($filter instanceof CollectionFilter) {
        echo $filter->getField(); // tags
        print_r($filter->getValues()); // ['foo', 'bar']
    }

    if ($filter instanceof StringMatchFilter) {
        echo $filter->getField(); // name
        echo $filter->getValue(); // 'foo'
        echo $filter->getOperator(); // StringMatchFilter::STARTS_WITH
        var_dump($filter->isNegated()); // true
    }
}
```

Now, we can ask our persistence system (Doctrine, ElasticSearch, Solr, 3rd-party API, ...) to return books:

- From offset `100`, limit to `50` items
- Ordered by `author.name` (use your own logic to parse the field path)
- Published between `2019-01-01` and `2019-01-31`
- In category id `12`
- Matching tag `foo` OR `bar` (AND clauses [can also be set](doc/Filter.md))
- But their names MUST NOT start by `foo`.

Translating these value objects to query your database or API is now up to you! OpenCubes provides no bridge for the moment, but maybe in a near future.

Customization
-------------

[](#customization)

Each component comes with a lot of customization possibilities (query parameters, default settings, ...).

[Read More...](doc/Customization.md)

Besides, you can also create your own URI parsers / builders by implementing [the appropriate interfaces](src/Component/Pager/PagerUriManagerInterface.php).

HATEOAS
-------

[](#hateoas)

**OpenCubes** brings HATEOAS to your application by providing links for each component:

- Page / PageSize links
- Apply / remove sort link
- Apply / remove filter
- ...

Each native component comes with a default JSON serialization which exposes the appropriate Urls. Being JSONserializable is not mandatory for your own components, it has been designed for a ready-to-use implementation. Different serializations can be achieved through your favourite serializer ([Symfony](https://symfony.com/doc/current/components/serializer.html) / [JMS](https://jmsyst.com/libs/serializer) to name a few).

[Read More...](doc/HATEOAS.md)

Dive into components
--------------------

[](#dive-into-components)

- [The Pager Component](doc/Pager.md)
- [The Sort Component](doc/Sort.md)
- [The Filter Component](doc/Filter.md)
- [The BreakDown Component](doc/BreakDown.md)

Installation
------------

[](#installation)

*OpenCubes is still at its early stage of development and subject to breaking changes.*

*Feel free to contribute or report any issue.*

```
composer require bentools/opencubes:1.0.x-dev
```

Tests
-----

[](#tests)

```
./vendor/bin/phpunit
```

License
-------

[](#license)

MIT.

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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.

###  Release Activity

Cadence

Every ~5 days

Total

2

Last Release

2612d ago

### Community

Maintainers

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

---

Top Contributors

[![bpolaszek](https://avatars.githubusercontent.com/u/5569077?v=4)](https://github.com/bpolaszek "bpolaszek (48 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/bentools-opencubes/health.svg)

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

###  Alternatives

[symfony/form

Allows to easily create, process and reuse HTML forms

2.8k152.1M2.8k](/packages/symfony-form)[sentry/sentry

PHP SDK for Sentry (http://sentry.io)

1.9k227.1M273](/packages/sentry-sentry)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[nelmio/api-doc-bundle

Generates documentation for your REST API from attributes

2.3k63.6M233](/packages/nelmio-api-doc-bundle)[phpbench/phpbench

PHP Benchmarking Framework

2.0k13.0M627](/packages/phpbench-phpbench)[symfony/rate-limiter

Provides a Token Bucket implementation to rate limit input and output in your application

26847.2M147](/packages/symfony-rate-limiter)

PHPackages © 2026

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