PHPackages                             precore/precore - 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. precore/precore

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

precore/precore
===============

Common classes and utilities

3.0.0(8y ago)1427.9k1MITPHPPHP &gt;=7.1

Since May 14Pushed 8y ago2 watchersCompare

[ Source](https://github.com/szjani/precore)[ Packagist](https://packagist.org/packages/precore/precore)[ RSS](/packages/precore-precore/feed)WikiDiscussions 3.0 Synced 3w ago

READMEChangelog (2)Dependencies (6)Versions (42)Used By (1)

precore
=======

[](#precore)

[![Latest Stable Version](https://camo.githubusercontent.com/2cec34441692a1457e2a284fbfa71155ca594715585e43923284fb2108c62986/68747470733a2f2f706f7365722e707567782e6f72672f707265636f72652f707265636f72652f762f737461626c652e706e67)](https://packagist.org/packages/precore/precore)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/e7ec790cae5b92e900918326091c2ff58b8415408cb55c0604e19d173ec15b5a/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f737a6a616e692f707265636f72652f6261646765732f7175616c6974792d73636f72652e706e673f623d322e31)](https://scrutinizer-ci.com/g/szjani/precore/?branch=2.1)[![SensioLabsInsight](https://camo.githubusercontent.com/3d994ff11c2ed6e75c3b35aeb731e28da6ff400a9e86b05e660d5c3bf3856146/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f66303039373735322d333763352d343461322d393665382d3333303463613638376636372f6d696e692e706e67)](https://insight.sensiolabs.com/projects/f0097752-37c5-44a2-96e8-3304ca687f67)[![Gitter chat](https://camo.githubusercontent.com/a4282cab002480ead00040ef3136439bb8464d2545e9886713dd8b8617010c9d/68747470733a2f2f6261646765732e6769747465722e696d2f737a6a616e692f707265636f72652e706e67)](https://gitter.im/szjani/precore)

master2.1[![Build Status](https://camo.githubusercontent.com/c113de061e098d6bda6e61c28cf4227e2949eb9e097847994587fae8af6d2bfa/68747470733a2f2f7472617669732d63692e6f72672f737a6a616e692f707265636f72652e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/szjani/precore)[![Build Status](https://camo.githubusercontent.com/7adaf5dfa1836b1095898e8ba3cb783b36ef27093cec8ea56b6b856017789d4f/68747470733a2f2f7472617669732d63692e6f72672f737a6a616e692f707265636f72652e706e673f6272616e63683d322e31)](https://travis-ci.org/szjani/precore)[![Coverage Status](https://camo.githubusercontent.com/d9ffba809a6770dbd15e8dbbb3bb2ecd34744b9f277ddb53c7322f8c9525d13c/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f737a6a616e692f707265636f72652f62616467652e706e673f6272616e63683d6d6173746572)](https://coveralls.io/r/szjani/precore?branch=master)[![Coverage Status](https://camo.githubusercontent.com/d2a04a8e8e942a3595dd7c9464b5be42242769abc46892f0a007ab08f274f8b0/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f737a6a616e692f707265636f72652f62616467652e706e673f6272616e63683d322e31)](https://coveralls.io/r/szjani/precore?branch=2.1)Precore is a common library which based on ideas coming from the Java world.

1. [Object and ObjectClass](https://github.com/szjani/precore#1-object-and-objectclass)
2. [Enum](https://github.com/szjani/precore#2-enum)
3. [Error handling](https://github.com/szjani/precore#3-error-handling)
4. [Object utilities](https://github.com/szjani/precore#4-object-utilities)
5. [Preconditions](https://github.com/szjani/precore#5-preconditions)
6. [Stopwatch](https://github.com/szjani/precore#6-stopwatch)
7. [Profiler](https://github.com/szjani/precore#7-profiler)
8. [Collections](https://github.com/szjani/precore#8-collections)
9. [String utilities](https://github.com/szjani/precore#9-string-utilities)
10. [Optional](https://github.com/szjani/precore#10-optional)
11. [Range](https://github.com/szjani/precore#11-range)
12. [TryTo](https://github.com/szjani/precore#12-tryto)

For more information, click on the items. If you need even more information, check the phpdoc.

1. BaseObject and ObjectClass

---

In Java, all objects are implicitly extend the `BaseObject` class. It is really convenient since some common methods are defined for all objects. This behavior is missing from PHP, therefore precore provides `precore\lang\BaseObject`. Sometimes it is required to be able to enforce in an interface, that the implementation must be an `BaseObject`, thus `precore\lang\ObjectInterface` can be used for that.

- `BaseObject::objectClass()` static function, returns the `ObjectClass` for the particular class
- `BaseObject::getObjectClass()` the same, but non-static method
- `BaseObject::className()` the same as `AnyClass::class` in PHP 5.5
- `BaseObject::getClassName()` returns the class name of the actual object
- `BaseObject::hashCode()` returns `spl_object_hash($this)`
- `BaseObject::equals(ObjectInterface $object)` returns true if the actual object and the argument are equal
- `BaseObject::toString()` and `BaseObject::__toString()`: both return the string representation of the object (the default format is: `{className}@{hashCode}`)
- `BaseObject::getLogger()` retrieves an [lf4php](https://github.com/szjani/lf4php) logger object for the actual class

The `ObjectClass` class extends `ReflectionClass` and gives some more features. These objects are cached if we get them through `ObjectClass::forName($className)` function. `ObjectClass` also supports resources (almost as in Java) in case of classes follow PSR-0.

2. Enum

---

In PHP unfortunately there is no Enum. `precore\lang\Enum` is an abstract class which tries to solve this lack of feature. Our enum class must extends this class and all possible values must be defined as public static variables which will be automatically found and initialized by precore.

```
final class Color extends Enum
{
    public static $RED;
    public static $GREEN;
    public static $BLUE;
}
Color::init();

function printName(Color $color) {
    echo $color->name() . PHP_EOL;
}

printName(Color::$RED);
foreach (Color::values() as $color) {
    printName($color);
}
```

It produces the following output:

```
RED
RED
GREEN
BLUE

```

3. Error handling

---

In several cases, PHP trigger errors instead of exceptions. Precore can automatically handle these errors and convert them into exception. The only thing should be done:

```
ErrorHandler::register();
```

After that, we will be able to catch specific exceptions. For the available exceptions see `precore\util\error` namespace.

4. Object utilities

---

### ToStringHelper

[](#tostringhelper)

Creating a string representation of an object is important, but not an exciting thing and we always need to use almost the same boilerplate code. With `precore\util\ToStringHelper`it can be simplified. A new instance can be created through `Objects::toStringHelper()` as well.

```
namespace HelloWorld;

class Foo {
    private $bar = 'foobar';

    public function __toString()
    {
        return Objects::toStringHelper($this)
            ->add('bar', $this->bar)
            ->toString();
    }
}

echo (string) new Foo();
// prints 'HelloWorld\Foo{bar=foobar}'
```

It supports arrays and `DateTime` as well. If the `ErrorHandler` is registered, `spl_object_hash()` will be used for those objects which cannot be cast to string.

### Equality

[](#equality)

Two variables equality can be checked with `Objects::equal($a, $b)`. It supports null, primitive types, objects, and `ObjectInterface` implementations as well as it is expected.

### Comparing objects

[](#comparing-objects)

Objects can be compared if they implement `precore\lang\Comparable` or if proper `precore\util\Comparator` is used which can compare the given objects. In several cases, comparing two objects depend on their member variables so they need to be compared as well. It also can be simplified with `precore\util\ComparisonChain`.

```
$strcmp = function ($left, $right) {
    return strcmp($left, $right);
};
$result = ComparisonChain::start()
    ->withClosure('aaa', 'aaa', $strcmp)
    ->withClosure('abc', 'bcd', $strcmp)
    ->withClosure('abc', 'bcd', $strcmp)
    ->result();
// $result < 0, because abc < bcd
```

In the previous example, the third comparison will not be executed, since it is unnecessary.

`Ordering` is a class which you can fine tune any `Comparator` object. This class also implements `Comparator` interface.

```
$ordering = Ordering::natural()
    ->compound(
        Collections::comparatorFrom(
            function (Bug $bug1, Bug $bug2) {
                return $bug1->priority() - $bug2->priority();
            }
        )
    )
    ->reverse();
Arrays::sort($bugs, $ordering);
```

The above ordering based on the fact that `Bug` class implements `Comparable` (natural ordering), but when two bugs are equal, their priority is compared to each other, moreover the final order will be reversed.

5. Preconditions

---

It is a very lightweight assertion tool, which supports argument, object state, null value, and array index checking. Customized messages can be passed with arguments similar to `printf()`.

```
/**
 * @param $number
 * @throws \InvalidArgumentException if $number is 0
 */
function divide($number) {
    Preconditions::checkArgument($number != 0, 'Division by zero');
    return $this->value / Preconditions::checkNotNull($number, 'Argument cannot be null');
}
```

6. Stopwatch

---

Useful for performance measurement, logging, and recognizing bottlenecks. Its `__toString()` method returns the elapsed time with the best abbreviate.

```
$stopwatch = Stopwatch::createStarted();
// ... doing something
echo $stopwatch->elapsed(TimeUnit::$MILLISECONDS);
// ... doing something
echo $stopwatch;
$stopwatch->reset();
$stopwatch->start();
```

7. Profiler

---

### Basics

[](#basics)

It helps the developer gather performance data. A profiler consists one or more stopwatches. Stopwatches are driven by statements in the source code.

```
$profiler = new Profiler('p1');
$profiler->start('t1');
$profiler->start('t2');
$profiler->stop();
$profiler->printOut();
```

The output of the above program would something like this:

```
 + Profiler [p1]
 |-- elapsed time                           [t1]     1 ms.
 |-- elapsed time                           [t2]     2 ms.
 |-- Total                                  [p1]     3 ms.

```

It also supports nested profilers.

```
$profiler = new Profiler('p1');
$profiler->start('t1');
$profiler->startNested('np1');

// this should be in another method
$nested = ProfilerRegistry::instance()->get('np1');
$nested->start('np1-t1');
$nested->stop();
// ----------------------

$profiler->start('t2');
$profiler->stop();
$profiler->printOut();
```

And the output:

```
 + Profiler [p1]
    + Profiler [np1]
    |-- elapsed time                       [np1-t1]     0 µs.
    |-- Subtotal                              [np1]  4.501 ms.
 |-- elapsed time                           [t1]  5.001 ms.
 |-- elapsed time                           [t2]     0 µs.
 |-- Total                                  [p1]  5.501 ms.

```

### AOP

[](#aop)

With `precore`, you can use an annotation on methods for profiling them. For this feature, you need to load and configure [Go! AOP PHP](https://github.com/lisachenko/go-aop-php). You have to register `ProfileLogAspect` in your `AspectKernel` implementation. This aspect manages the necessary `Profiler` objects and the output will be logged via `lf4php`. If you run the unit tests of `precore`, you will see the output of a test case.

```
class ProfileFixture
{
    /**
     * @Profile(name="Main process")
     */
    public function main()
    {
        $this->foo1();
        $this->foo2();
    }

    /**
     * @Profile
     */
    protected function foo1()
    {
        $this->bar();
    }

    /**
     * @Profile
     */
    protected function bar()
    {
    }

    /**
     * @Profile(name="very fast method")
     */
    protected function foo2()
    {
    }
}

$fixture = new ProfileFixture();
$fixture->main();
```

In the log:

```
 + Profiler [Main process]
    + Profiler [foo1]
        + Profiler [bar]
        |-- elapsed time                         [exec]     0 µs.
        |-- Subtotal                              [bar]   26.5 ms.
    |-- elapsed time                         [exec]     27 ms.
    |-- Subtotal                             [foo1]     27 ms.
    + Profiler [very fast method]
    |-- elapsed time                         [exec]     0 µs.
    |-- Subtotal                 [very fast method]     0 µs.
 |-- elapsed time                         [exec]   30.5 ms.
 |-- Total                        [Main process]   30.5 ms.

```

8. Collections

---

Collection related static functions help you sorting objects. The comparing logic can be based on the `compareTo` method if objects implement `Comparable` interface, or you can utilize a `Comparator`. Currently `ArrayObject` instances and `array`s can be sorted, and an `SplHeap` implementation can be created for that. `StringComparator` enum contains the 4 basic string comparison algorithm provided by PHP.

Using a heap to sort strings in natural order:

```
$heap = Collections::createHeap(Collections::reverseOrder(StringComparator::$NATURAL));
$heap->insert('rfc1.txt');
$heap->insert('rfc2086.txt');
$heap->insert('rfc822.txt');
foreach ($heap as $string) {
    echo $string . "\n";
}
```

The above program results the following output:

```
rfc1.txt
rfc822.txt
rfc2086.txt

```

A more complex example, where the given people should be sorted according to their name. If the name is the same, their age must be considered:

```
final class Person implements Comparable
{
    private $name;
    private $age;

    public function __construct($name, $age)
    {
        $this->name = Preconditions::checkNotNull($name);
        $this->age = Preconditions::checkNotNull($age);
    }

    public function compareTo($object)
    {
        ObjectClass::forName(__CLASS__)->cast(Preconditions::checkNotNull($object));
        /* @var $object Person */
        return ComparisonChain::start()
            ->withComparator($this->name, $object->name, StringComparator::$NATURAL_CASE_INSENSITIVE)
            ->withClosure($this->age, $object->age, function ($age1, $age2) {
                return $age1 - $age2;
            })
            ->result();
    }

    public function __toString()
    {
        return Objects::toStringHelper($this)
            ->add($this->name)
            ->add($this->age)
            ->toString();
    }
}

$array = [
    new Person('John', 21),
    new Person('Johnny', 10),
    new Person('John', 70),
    new Person('Mary', 13)
];
Arrays::sort($array);
echo Joiner::on(', ')->join($array);
```

This program prints out the following:

```
Person{John, 21}, Person{John, 70}, Person{Johnny, 10}, Person{Mary, 13}

```

### Predicates

[](#predicates)

A predicate is a function that has one input parameter, and the return value is true or false. This class provides the most common predicates. Predicates are useful e.g. for filtering.

### Iterator based utilities

[](#iterator-based-utilities)

`Iterators` and `Iterables` provides static factories to transform, filter or limit `Iterator`s or `IteratorAggregate`s. These things can be easily used with `FluentIterable`.

```
$topAdminUserNames = FluentIterable::from($repository->getUsers())
  ->filter($hasAdminRoleFilter)
  ->transform($userNameTransformer)
  ->limit(10);
```

In the above example, `$hasAdminRoleFilter` is a predicate that accept a user if that is an administrator, `$userNameTransformer` returns the name of the input user. Iterating over `$topAdminUserNames` results 10 user names.

#### BufferedIterable

[](#bufferediterable)

If you need to iterate over huge amount of data, you can use `BufferedIterable`. The given `ChunkProvider` is responsible to provide data chunks which are being consumed by the `BufferedIterable`.

```
$userProvider = function ($offset) {
    return $userRepository->get($offset, 10);
}
$adminFilter = function ($user) {
    return $user->isAdmin();
}
$top100AdminUsers = BufferedIterable::withChunkFunction($userProvider)
    ->filter($adminFilter)
    ->providerCallLimit(40)
    ->limit(100);
foreach ($top100AdminUsers as $admin) {
    // do something
}
```

In this example the chunk provider loads 10 users in each call, and the `$adminFilter` is a predicate to filter administrators. When we iterate over `$top100AdminUsers` we get 100 administrator users. Provider call limit is for avoiding infinite loop when the chunk provider never returns empty chunk and there is no limit, or even the filter can cause such an issue. Its default value is 1, here 40 is a reasonable choice.

9. String utilities

---

### Joiner

[](#joiner)

Although PHP provides `implode()` function, skipping or replacing `null`s is not simple, moreover `array` or `DateTime` cannot be passed as parameter. Joiner solves all of it.

```
$joiner = Joiner::on(', ')->skipNulls();
$joiner->join(['Harry', null, 'Ron', 'Hermione']);
// returns 'Harry, Ron, Hermione'
```

### Splitter

[](#splitter)

Splitter is the opposite of `Joiner`. Compared with `explode()`, it can trim the results, and skip empty strings.

```
$result = Splitter::on(',')
    ->trimResults()
    ->omitEmptyStrings()
    ->split('foo,bar, ,   qux');
```

The `$result` variable is a `Traversable`, iterating over it the following items will be provided: `'foo', 'bar', 'qux'`

Splitting is possible with a regular expression:

```
$result = Splitter::onPattern('/[\s,]+/')->split('hypertext language, programming');
```

The output is the following: `'hypertext', 'language', 'programming'`

It is also possible to split strings into substrings of a specified fixed length:

```
$result = Splitter::fixedLength(3)->split('1234567');
```

The result will be the following: `'123', '456', '7'`

10. Optional

---

A container object which may or may not contain a non-null value. If a value is present, `isPresent()` will return true and `get()` will return the value. Additional methods that depend on the presence or absence of a contained value are provided, such as `orElse()` (return a default value if value not present) and `ifPresent()` (execute a block of code if the value is present).

```
function randOrNull() {
    return mt_rand(0, 1) === 0 ? mt_rand(0, 100) : null;
}

$printOut = function ($value) {
    echo $value . PHP_EOL;
};

$range = Range::closed(20, 30);
for ($i = 0; $i < 100; $i++) {
    Optional::ofNullable(randOrNull())
        ->filter($range)
        ->ifPresent($printOut);
}
```

This code generates 100 random numbers or null values and all values will be printed out if that is a number and within the given range (20 &lt;= x &lt;= 30). We do not need to do null checks, rather we can use fluent interfaces.

11. Range

---

A range is an interval, defined by two endpoints. Ranges may "extend to infinity" -- for example, the range "x &gt; 3" contains arbitrarily large values -- or may be finitely constrained, for example "2 &lt;= x &lt; 5".

The endpoints and the values passed to query methods must be able to be compared. This comparison can be explicitly set, but `Range` supports natural ordering on the following types:

- strings (strcmp)
- numbers
- DateTime
- boolean

It also supports objects that implement `Comparable` interface, like the `Enum`.

Range objects can be created via static factory methods. The following range is open on both sides, only 'c' and 'd' chars are within the range.

```
$range = Range::open('b', 'e');
assertFalse($range->contains('b'));
assertTrue($range->contains('c'));
```

There are query methods like `isConnected()` or `encloses()`, but ranges can be composed by `intersection()` or `span()`. `Range` is immutable.

12. TryTo

---

`TryTo` can be used to handle errors in a functional way.

```
$result = TryTo::run(function () use ($a, $b) {
    Preconditions::checkArgument($b !== 0);
    return $a / $b;
});
```

This example shows how a possible error can be gracefully handled. If `$b` is 0, `$result` will be a `Failure` object which holds the thrown `InvalidArgumentException`. Otherwise it is a `Success` and contains the calculated value.

It is also possible the handle only a predefined set of exception types.

```
$result = TryTo::catchExceptions([InvalidArgumentException::class])
    ->run(function () use ($a, $b) {
        Preconditions::checkArgument($b !== 0);
        return Preconditions::checkNotNull($a) / Preconditions::checkNotNull($b);
    });
```

Although the `InvalidArgumentException` is handled just like before, if one of the given parameters is null the thrown `NullPointerException` will not be caught by `TryTo`.

We can also pass recovery functions and/or run a function in case of failure:

```
$result = TryTo::catchExceptions()
    ->run(function () use ($a, $b) {
        Preconditions::checkArgument($b !== 0);
        return Preconditions::checkNotNull($a) / Preconditions::checkNotNull($b);
    })
    ->onFail(NullPointerException::class, function (NullPointerException $e) {
        self::getLogger()->error('Null parameter has been passed', [], $e);
    })
    ->recoverFor(InvalidArgumentException::class, function() {
        return PHP_INT_MAX;
    });
```

If the divisor is 0, the `$result` is `Success` and contains `PHP_INT_MAX`. Otherwise `$result` is a `Success` and holds the calculated value or `Failure` due to a null parameter.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity31

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity70

Established project with proven stability

 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 ~44 days

Recently: every ~233 days

Total

41

Last Release

3018d ago

Major Versions

1.11.0 → 2.0.02015-08-30

2.1.x-dev → 3.0.02018-03-19

PHP version history (4 changes)1.0.0PHP &gt;=5.3.0

1.9.0PHP &gt;=5.4.0

2.1.0PHP &gt;=5.5.0

3.0.0PHP &gt;=7.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/545872?v=4)[Janos Szurovecz](/maintainers/szjani)[@szjani](https://github.com/szjani)

---

Top Contributors

[![szjani](https://avatars.githubusercontent.com/u/545872?v=4)](https://github.com/szjani "szjani (1 commits)")

---

Tags

common

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[phpoffice/common

PHPOffice Common

23512.6M36](/packages/phpoffice-common)[prooph/common

Common classes used across prooph packages

842.2M28](/packages/prooph-common)

PHPackages © 2026

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