PHPackages                             popov/variably - 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. popov/variably

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

popov/variably
==============

The powerful, simple and fast engine for handle variables in string

3199PHP

Since Jun 19Pushed 7y ago3 watchersCompare

[ Source](https://github.com/popovserhii/variably)[ Packagist](https://packagist.org/packages/popov/variably)[ RSS](/packages/popov-variably/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependenciesVersions (1)Used By (0)

The powerful, simple and fast engine for handle scalars and stringable variables
================================================================================

[](#the-powerful-simple-and-fast-engine-for-handle-scalars-and-stringable-variables)

**Filters** and **Preparation** give huge flexibility for handle data. You can get any type of data from HTML, CSV, Excel, SpreadSheet, Amazon etc. and build filters chain for get the best value that you need.

Variably has expendable config base which allow setup any element with any requirements.

**Filters** do delicate and precision work, this concentrate on unique filed (but not necessarily).

**Preparation** do the same but use more resource for handle data, this can use database or third party services or any other volume processing.

For example the next filters chain explode string to array by space, get first element of array and parse it as float.

```
// value: "4.9 of 5 stars"
[
    'star' => ['name' => 'star', '__filter' => ['explode', 'shift', 'float']],
]
// result: 4.9
```

In most cases you should use **Filters**. Use **Preparation** carefully.

Filters
-------

[](#filters)

#### **`br2nl`**

[](#br2nl)

Replace any `` HTML tag in string to new line symbol (`\r\n`).

```
# object notation
(new FilterBr2nl())->filter('Hello, World! I am Skynet.');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['br2nl']],
]

# result
// Hello, World!
// I am Skynet.
```

#### **`concat`**

[](#concat)

Concatenate two and more strings.

```
# object notation
(new FilterConcat())->filter('Hello, World! ')->setConfig(['params' => ['I am Skynet.']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['concat:I am Skynet.']],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [['name' => 'concat', 'params' => ['I am Skynet.']]]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [['name' => 'concat', 'params' => ['I ', 'am ', 'Skynet.']]]],
]

# result
// Hello, World! I am Skynet.
```

#### **`dateExcel`**

[](#dateexcel)

Convert [*Excel serial number*](https://support.office.com/en-us/article/convert-dates-stored-as-text-to-dates-8df7663e-98e6-4295-96e4-32a67ec0a680) to standard date format

What is an Excel serial number?

Excel stores dates as sequential serial numbers so that they can be used in calculations. By default, January 1, 1900, is serial number 1, and January 1, 2008, is serial number 39448 because it is 39,448 days after January 1, 1900.

```
# object notation
(new FilterDateExcel())->filter('42622');
(new FilterDateExcel())->filter('42622')->setConfig(['params' => ['formatFrom' => 'Y-m-d']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['dateExcel']],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateExcel', 'params' => ['formatFrom' => 'Y-m-d']]
    ]],
]

# result
// 2016-09-09
```

**Params**

- `formatTo` - output date format, default takes 'Y-m-d'
- `timezone` - date timezone, by default takes system timezone

#### **`dateTime`**

[](#datetime)

Convert string to standard date format

```
# object notation
(new FilterDateTime())->filter('12.07.2018');
(new FilterDateTime())->filter('12.07.2018')->setConfig(['params' => ['formatFrom' => 'd.m.Y']]);
(new FilterDateTime())->filter('12.07.2018')->setConfig(['params' => ['formatFrom' => 'd.m.Y', 'formatTo' => 'Y-m-d H:i:s']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['dateTime']],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateTime', 'params' => ['formatFrom' => 'd.m.Y']]
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateTime', 'params' => ['formatFrom' => 'd.m.Y', 'formatTo' => 'Y-m-d H:i:s']]
    ]],
]

# result
// 2018-07-12 00:00:00
```

**Params**

- `fromartFrom` - input date format
- `formatTo` - output date format, default is 'Y-m-d H:i:s'
- `timezone` - date timezone, by default takes system timezone

#### **`dateNative`**

[](#datenative)

Convert native date or datetime value to standard format *(requires Intl library)*.

```
# object notation
(new FilterDateNative())->filter('20 enero 2018')->setConfig(['params' => ['locale' => 'es_ES']]); // es
(new FilterDateNative())->filter('2 février 2018')->setConfig(['params' => ['locale' => 'fr_FR']]); // fr
(new FilterDateNative())->filter('May 16, 2016')->setConfig(['params' => ['locale' => 'en_GB']]); // en
(new FilterDateNative())->filter('27. Juni 2014')->setConfig(['params' => ['locale' => 'de_DE']]); // de

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateNative', 'params' => ['locale' => 'es_ES']]
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateNative', 'params' => ['locale' => 'fr_FR']]
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateNative', 'params' => ['locale' => 'en_GB']]
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'dateNative', 'params' => ['locale' => 'de_DE']]
    ]],
]

# result
// 2018-01-20
// 2018-02-02
// 2016-05-16
// 2014-06-27
```

**Params**

- `locale` - [list](https://stackoverflow.com/a/20818686/1335142) of locales (may be not full)
- `format_to` - convert date to format. Default is *Y-m-d*.

#### **`explode`**

[](#explode)

Explode string by delimeter. As default delimeter is taken " " (space).

```
# object notation
(new FilterExplode())->filter('apple, peas, strawberry, cherry');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['explode']],
]

# result
// ['apple', 'peas', 'strawberry', 'cherry']
```

#### **`multiExplode`**

[](#multiexplode)

Explode string by delimeters. If no delimeters set the " " (space) will be used by default.

```
# object notation
(new FilterMultiExplode())->filter('apple, peas? strawberry, cherry')->setConfig(['params' => [',','?']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['name' => 'multiExplode', 'params' => ['/', '?']]],
]

# result
// ['apple', 'peas', 'strawberry', 'cherry']
```

#### **`float`**

[](#float)

Parse stringable number to float.

```
# object notation
(new FilterFloat())->filter(4.5);
(new FilterFloat())->filter('4.5');
(new FilterFloat())->filter('4,5');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['float']],
]

# result
// 4.5
```

#### **`htmlEntityDecode`**

[](#htmlentitydecode)

To decode an entity into a character, `htmlEntityDecode` needs to know what encoding you'd like your character to be in. "ü" can be represented in Latin-1, UTF-8, UTF-16 and a host of other encodings. The default is Latin-1. – (–, EN DASH) cannot be represented in Latin-1. Hence it stays unchanged. Tell `htmlEntityDecode` to decode it into an encoding that can represent that character, like UTF-8:

```
# object notation
(new FilterHtmlEntityDecode())->filter('Hello &#8211; World!');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['htmlEntityDecode']],
]

# result
// Hello – World!
```

#### **`int`**

[](#int)

Parse stringable number to int

```
# object notation
(new FilterInt())->filter(4.5);
(new FilterInt())->filter('009945');
(new Filterint())->filter('009945-john');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['int']],
]

# result
// 4
// 9945
// 9945
```

#### **`merge`**

[](#merge)

Merge value to other array. All scalar values will be converted to array, object will be skipped

```
# object notation
(new FilterMerge())->filter(4)->setConfig(['params' => [
    [5, 10],
    [20, 30]
]]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'merge', 'params' => [
            [5, 10],
            [20, 30]
        ]]
    ]]
],

# result
// [4, 5, 10, 20, 30]
```

#### **`number`**

[](#number)

Delete all non number symbols from value

```
# object notation
(new FilterNumber())->filter('(093) 234-56-78');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['number']],
]

# result
// 0932345678
```

#### **`percentageToQuantity`**

[](#percentagetoquantity)

Convert percentage of total to quantity

```
# object notation
(new FilterPercentageToQuantity())->filter('20%')->setConfig(['params' => ['total' => '15']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'percentageToQuantity', 'params' => ['total' => '15']]
    ]],
]

# result
// 3

# workflow: round((15 / 100) * 20)
```

#### **`percentToNumber`**

[](#percenttonumber)

Convert percent value to integer

```
# object notation
(new FilterPercentToNumber())->filter('3%');
(new FilterPercentToNumber())->filter(0.03);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['percentToNumber']],
]

# result
// 3
```

#### **`pop`**

[](#pop)

Return last element of array

```
# object notation
(new FilterPop())->filter(['apple', 'peas', 'strawberry', 'cherry']);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['pop']],
]

# result
// 'cherry'
```

#### **`shift`**

[](#shift)

Return first element or array

```
# object notation
(new FilterPop())->filter(['apple', 'peas', 'strawberry', 'cherry']);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['shift']],
]

# result
// 'apple'
```

#### **`regexMatch`**

[](#regexmatch)

Return matched elements in regular expression

```
# object notation
(new FilterRegexMatch())->filter('a-star-small-5')->setConfig(['params' => ['/a-star[-\w]*-([0-5])/']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['regexMatch:/a-star[-\w]*-([0-5])/']],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'regexMatch', 'params' => ['/a-star[-\w]*-([0-5])/']]
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'regexMatch', 'params' => ['pattern' => '/a-star[-\w]*-([0-5])/']]
    ]],
]

# result
// [5]
```

#### **`replace`**

[](#replace)

Replace all occurrences of the search string with the replacement string

```
# object notation
(new FilterReplace())->filter('One')->setConfig(['params' => ['from' => 'One', 'to' => 1]]);
(new FilterReplace())->filter('Eine')->setConfig(['params' => ['from' => ['One', 'Eine', 'Une'], 'to' => 1]]);
(new FilterReplace())->filter('Une')->setConfig(['params' => ['from' => ['One', 'Eine', 'Une'], 'to' => 1]]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'replace', 'params' => [['One', 'Eine', 'A una', 'Una', 'Une'], 1]],
    ]],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'replace', 'params' => ['from' => ['One', 'Eine', 'A una', 'Una', 'Une'], 'to' => 1]],
    ]],
]

# result
// 1
```

#### **`toLower`**

[](#tolower)

Convert string to lower case

```
# object notation
(new FilterToLower())->filter('aPpLe');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['toLower']],
]

# result
// 'apple'
```

#### **`toUpper`**

[](#toupper)

Convert string to upper case

```
# object notation
(new FilterToLower())->filter('apple');

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['toUpper']],
]

# result
// 'APPLE'
```

#### **`trim`**

[](#trim)

Trim string. By default white spaces are trimmed

```
# object notation
(new FilterTrim())->filter(' apple  ');
(new FilterTrim())->filter('~apple~')->setConfig(['params' => ['charList' => '~']]);

# config notation
[
    'fieldName' => ['name' => 'fieldName', '__filter' => ['trim']],
]
// or
[
    'fieldName' => ['name' => 'fieldName', '__filter' => [
        ['name' => 'trim', 'params' => ['charList' => '~']]
    ]],
]

# result
// 'apple'
```

Preparation
-----------

[](#preparation)

// TODO

For Developers
--------------

[](#for-developers)

Don't hesitate improve functionality and create PR.

### Custom Filter

[](#custom-filter)

*Variably* module is standalone but in most cases is using with other modules for filtration imported data, handle email templates, etc.

#### Zend Framework 2/3

[](#zend-framework-23)

Example is shown when *Variably* works in pairs with [*Popov\\ZfcImporter*](https://github.com/popovserhii/zfc-importer)

```
// module/Custom/Module/config/module.config.php
return [
    'importer' => [
        'helpers' => [
            'CustomTagsFilter' => \Your\Module\Importer\CustomTagFilter::class,
        ],
        'tasks' => [
            'custom-task-name' => [
                'driver' => 'Excel',
                'fields' => [
                    [
                        'tag' => ['__filter' => ['customTags']],

                        '__table' => 'tags',
                        '__codename' => 'tag', // code name of position
                        '__identifier' => 'tag'
                    ],
                ],
            ],
        ],
    ]
];
```

###  Health Score

22

—

LowBetter than 21% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 81.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/7dbdbd3abed25e11e97a69bc611daa3fe33ad5d1805f2fb32d491c888c4dfb51?d=identicon)[Serhii Popov](/maintainers/Serhii%20Popov)

---

Top Contributors

[![popovserhii](https://avatars.githubusercontent.com/u/1991183?v=4)](https://github.com/popovserhii "popovserhii (26 commits)")[![DayOut](https://avatars.githubusercontent.com/u/7451037?v=4)](https://github.com/DayOut "DayOut (5 commits)")[![vladgemtyp](https://avatars.githubusercontent.com/u/12100554?v=4)](https://github.com/vladgemtyp "vladgemtyp (1 commits)")

### Embed Badge

![Health badge](/badges/popov-variably/health.svg)

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

###  Alternatives

[yiiext/nested-set-behavior

AR models behavior that allows to work with nested sets tree.

156122.7k1](/packages/yiiext-nested-set-behavior)

PHPackages © 2026

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