Skip to content

Commit 569c071

Browse files
author
Florian Eckerstorfer
committed
Implement basic functionality
1 parent dc03170 commit 569c071

24 files changed

+721
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/build
2+
/composer.lock
3+
/phpunit.xml
4+
/vendor

README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
Chain
2+
=====
3+
4+
> Chain provides you with a consistent and chainable way to work with arrays in PHP.
5+
6+
Made by [Florian Eckerstorfer](https://florian.ec) in Vienna, Europe.
7+
8+
9+
Motivation
10+
----------
11+
12+
Let us be honest. Working with arrays in PHP is a mess. First of all, you have to prefix most (but not all) functions
13+
with `array_`, the parameter ordering is not consistent. For example, `array_map()` expects the callback as first
14+
parameter and the array as the second, but `array_filter()` expects the array as first and the callback as second. You
15+
also have to wrap the function calls around the array, the resulting code is not nice to look, not readable and
16+
hard to understand.
17+
18+
```php
19+
$arr = array_filter(
20+
array_map(
21+
function ($v) { return rand(0, $v); },
22+
array_fill(0, 10, 20)
23+
),
24+
function ($v) { return $v & 1; }
25+
);
26+
```
27+
28+
Chain wraps the array in an object and gives you a chainable interface.
29+
30+
```php
31+
$arr = Chain::fill(0, 10, 20)
32+
->map(function ($v) { return rand(0, $v); })
33+
->filter(function ($v) { return $v & 1; });
34+
```
35+
36+
37+
Usage
38+
-----
39+
40+
Chain allows you to create, manipulate and access arrays.
41+
42+
### Array Creation
43+
44+
You can create a Chain by passing an array to the constructor.
45+
46+
```php
47+
$chain = new Chain([1, 2, 3]);
48+
```
49+
50+
In addition a Chain can also be created by the static `fill()` method, which is a wrapper for the `array_fill()`
51+
function.
52+
53+
```php
54+
$chain = Chain::fill(0, 10, 'foo');
55+
```
56+
57+
### Array Manipulation
58+
59+
Chains manipulation methods manipulate the underlying array and return the object, that is, they can be chained. Most
60+
of the methods are simple wrappers around the corresponding `array_` function.
61+
62+
In the following example `->map()` is used to multply each element by `3` and then filter the array to only contain
63+
odd elements.
64+
65+
```php
66+
$chain = (new Chain([1, 2, 3]))
67+
->map(function ($v) { return $v*3; })
68+
->filter(function ($v) { return $v & 1; });
69+
$chain->array; // -> [3, 9]
70+
```
71+
72+
When a method accepts an array (`->diff()` or `->intersect()`) then you can pass in another instance of `Chain`
73+
instead of the array.
74+
75+
#### List of Array Manipulation Methods
76+
77+
- `->diff(array|Chain)`
78+
- `->filter(callable)`
79+
- `->intersect(array|chain)`
80+
- `->map(callable)`
81+
82+
### Array Access
83+
84+
Most importantly you can access the underlying array using the public `chain` property.
85+
86+
```php
87+
$chain = new Chain([1, 2, 3]);
88+
$chain->array; // -> [1, 2, 3]
89+
```
90+
91+
Additionally `Chain` contains a number of methods to access properties of the array. In contrast to the manipulation
92+
methods these methods return a value instead of a reference to the `Chain` object. That is, array access methods are
93+
not chainable.
94+
95+
```php
96+
$chain = new Chain([1, 2, 3]);
97+
$chain->count(); // -> 3
98+
$chain->sum(); // -> 6
99+
100+
$chain->reduce(function ($current, $value) {
101+
return $current * $value;
102+
}, 1); // -> 6
103+
```
104+
105+
106+
#### List of Array Manipulation Methods
107+
108+
- `->count()`
109+
- `->reduce(callable[, int])`
110+
- `->sum()`

composer.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "cocur/chain",
3+
"description": "Consistent and chainable array manipulation",
4+
"autoload": {
5+
"psr-4": {"Cocur\\Chain\\": "src"}
6+
},
7+
"require-dev": {
8+
"phpunit/phpunit": "~4.8"
9+
}
10+
}

examples/diff-intersect-sum.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
use Cocur\Chain\Chain;
4+
5+
require_once __DIR__.'/../vendor/autoload.php';
6+
7+
echo array_sum(array_intersect(
8+
array_diff([1, 2, 3, 4, 5], [0, 1, 9]),
9+
array_filter([2, 3, 4], function ($v) { return !($v & 1); })
10+
));
11+
12+
echo "\n";
13+
14+
echo (new Chain([1, 2, 3, 4, 5]))
15+
->diff([0, 1, 9])
16+
->intersect((new Chain([2, 3, 4]))->filter(function ($v) { return !($v & 1); }))
17+
->sum();

examples/fill-map-filter.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
use Cocur\Chain\Chain;
4+
5+
require_once __DIR__.'/../vendor/autoload.php';
6+
7+
$arr = array_filter(
8+
array_map(
9+
function ($v) { return rand(0, $v); },
10+
array_fill(0, 10, 20)
11+
),
12+
function ($v) { return $v & 1; }
13+
);
14+
15+
print_r($arr);
16+
17+
$chain = Chain::fill(0, 10, 20)
18+
->map(function ($v) { return rand(0, $v); })
19+
->filter(function ($v) { return $v & 1; });
20+
print_r($chain->array);

phpunit.xml.dist

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<phpunit bootstrap="vendor/autoload.php" colors="true">
4+
<testsuites>
5+
<testsuite name="cocur/chain Test Suite">
6+
<directory>tests</directory>
7+
</testsuite>
8+
</testsuites>
9+
10+
<filter>
11+
<whitelist>
12+
<directory suffix=".php">src</directory>
13+
</whitelist>
14+
</filter>
15+
</phpunit>

src/Chain.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Cocur\Chain;
4+
5+
use Cocur\Chain\Link\Count;
6+
use Cocur\Chain\Link\Diff;
7+
use Cocur\Chain\Link\Fill;
8+
use Cocur\Chain\Link\Filter;
9+
use Cocur\Chain\Link\Intersect;
10+
use Cocur\Chain\Link\Map;
11+
use Cocur\Chain\Link\Reduce;
12+
use Cocur\Chain\Link\Sum;
13+
14+
/**
15+
* Chain
16+
*
17+
* @package Cocur\Chain
18+
* @author Florian Eckerstorfer
19+
* @copyright 2015 Florian Eckerstorfer
20+
*/
21+
class Chain
22+
{
23+
use Count,
24+
Diff,
25+
Filter,
26+
Fill,
27+
Intersect,
28+
Map,
29+
Reduce,
30+
Sum;
31+
32+
/**
33+
* @var array
34+
*/
35+
public $array;
36+
37+
/**
38+
* @param array $array
39+
*/
40+
public function __construct(array $array = [])
41+
{
42+
$this->array = $array;
43+
}
44+
}

src/Link/Count.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Cocur\Chain\Link;
4+
5+
/**
6+
* Count
7+
*
8+
* @package Cocur\Chain\Link
9+
* @author Florian Eckerstorfer
10+
* @copyright 2015 Florian Eckerstorfer
11+
*/
12+
trait Count
13+
{
14+
/**
15+
* @return int
16+
*/
17+
public function count()
18+
{
19+
return count($this->array);
20+
}
21+
}

src/Link/Diff.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Cocur\Chain\Link;
4+
5+
use Cocur\Chain\Chain;
6+
7+
/**
8+
* Diff
9+
*
10+
* @package Cocur\Chain\Link
11+
* @author Florian Eckerstorfer
12+
* @copyright 2015 Florian Eckerstorfer
13+
*/
14+
trait Diff
15+
{
16+
/**
17+
* @param Chain|array $array2
18+
*
19+
* @return Chain
20+
*/
21+
public function diff($array2)
22+
{
23+
$this->array = array_diff(
24+
$this->array,
25+
$array2 instanceof Chain ? $array2->array : $array2
26+
);
27+
28+
return $this;
29+
}
30+
}

src/Link/Fill.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Cocur\Chain\Link;
4+
5+
use Cocur\Chain\Chain;
6+
7+
/**
8+
* Fill
9+
*
10+
* @package Cocur\Chain\Link
11+
* @author Florian Eckerstorfer
12+
* @copyright 2015 Florian Eckerstorfer
13+
*/
14+
trait Fill
15+
{
16+
/**
17+
* @param int $startIndex
18+
* @param int $num
19+
* @param mixed $value
20+
*
21+
* @return Chain
22+
*/
23+
public static function fill($startIndex, $num, $value = null)
24+
{
25+
return new self(array_fill($startIndex, $num, $value));
26+
}
27+
}

0 commit comments

Comments
 (0)