PHPackages                             sebastiaanluca/php-pipe-operator - 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. sebastiaanluca/php-pipe-operator

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

sebastiaanluca/php-pipe-operator
================================

Method chaining (or fluent expressions) for any value using any method.

7.0.0(1y ago)288467.7k—4.2%13[1 PRs](https://github.com/sebastiaanluca/php-pipe-operator/pulls)2MITPHPPHP ^8.3.0CI passing

Since Feb 24Pushed 1y ago6 watchersCompare

[ Source](https://github.com/sebastiaanluca/php-pipe-operator)[ Packagist](https://packagist.org/packages/sebastiaanluca/php-pipe-operator)[ Docs](https://github.com/sebastiaanluca/php-pipe-operator)[ RSS](/packages/sebastiaanluca-php-pipe-operator/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (6)Dependencies (3)Versions (15)Used By (2)

PHP Pipe Operator
=================

[](#php-pipe-operator)

[![Latest stable release](https://camo.githubusercontent.com/6387400d0a71ac4c44fa5633bae24bdb0b2990af7a0c51b432a5bb5c22b4a784/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7365626173746961616e6c7563612f7068702d706970652d6f70657261746f722e7376673f6c6162656c3d737461626c65)](https://packagist.org/packages/sebastiaanluca/php-pipe-operator)[![Software license](https://camo.githubusercontent.com/08662bb339bee903c7279b82f3217310d3f196fdfa63b019d294ae85e1a5d7d7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d696e666f726d6174696f6e616c2e737667)](LICENSE.md)[![Build status](https://github.com/sebastiaanluca/php-pipe-operator/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/sebastiaanluca/php-pipe-operator/actions/workflows/test.yml?query=branch%3Amaster)[![Total downloads](https://camo.githubusercontent.com/0eb503caa068f2d7605341458f0ebb429b285ec3412999fef709d3c4a909840f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7365626173746961616e6c7563612f7068702d706970652d6f70657261746f722e7376673f636f6c6f723d627269676874677265656e)](https://packagist.org/packages/sebastiaanluca/php-pipe-operator)[![Total stars](https://camo.githubusercontent.com/eb6166ffec2d9615431fc0385d55d814cd6ff59bb0abddc73779542e940deab0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f7365626173746961616e6c7563612f7068702d706970652d6f70657261746f722e7376673f636f6c6f723d627269676874677265656e)](https://github.com/sebastiaanluca/php-pipe-operator)

[![Visit my website](https://camo.githubusercontent.com/e7ba677e5ab3656d011565d194b881ee2051defb4970c19b63e8a210a53d9794/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c696e6b2d776562736974652d6c69676874677265792e737667)](https://sebastiaanluca.com)[![View my other packages and projects](https://camo.githubusercontent.com/5ce3a83ee0ec2b4ae47a99f67347c1d8e78582757eca80fe31c98e5bd0e2185a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c696e6b2d6f746865725f7061636b616765732d6c69676874677265792e737667)](https://packagist.org/packages/sebastiaanluca)[![Follow @sebastiaanluca on Twitter](https://camo.githubusercontent.com/bde346ed8efc8b2458386b36256c64e3fe010276f449b80fe4f663c4c8bbd83e/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f7365626173746961616e6c7563612e7376673f7374796c653d736f6369616c)](https://twitter.com/sebastiaanluca)[![Share this package on Twitter](https://camo.githubusercontent.com/cb820a0ecc9645168e33b03925d7f14691262ddbaeaf66a0a91697803d0cba2d/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f75726c2f687474702f736869656c64732e696f2e7376673f7374796c653d736f6369616c)](https://twitter.com/intent/tweet?text=Use%20PHP%27s%20pipe%20operator%20now!%20https%3A%2F%2Fgithub.com%2Fsebastiaanluca%2Fphp-pipe-operator%20via%20%40sebastiaanluca)

Method chaining (or fluent expressions) **for any value using any method.**

Table of contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [How to install](#how-to-install)
- [How to use](#how-to-use)
    - [The basics](#the-basics)
    - [Using first class callable syntax (enabling IDE autocompletion)](#using-first-class-callable-syntax-enabling-ide-autocompletion)
    - [Using closures](#using-closures)
    - [Using class methods](#using-class-methods)
- [What does it solve?](#what-does-it-solve)
    - [A simple example](#a-simple-example)
    - [Another way of writing](#another-way-of-writing)
    - [More examples of the issue at hand](#more-examples-of-the-issue-at-hand)
- [Notes](#notes)
- [License](#license)
- [Change log](#change-log)
- [Testing](#testing)
- [Contributing](#contributing)
- [Security](#security)
- [Credits](#credits)
- [About](#about)

Requirements
------------

[](#requirements)

- PHP 8.1 or 8.2

How to install
--------------

[](#how-to-install)

Via Composer:

```
composer require sebastiaanluca/php-pipe-operator
```

How to use
----------

[](#how-to-use)

### The basics

[](#the-basics)

The basic gist of the package is that it takes a value and performs one or more actions on it. A simple example:

```
use SebastiaanLuca\PipeOperator\Pipe;

Pipe::from('hello')->strtoupper()->get();

// "HELLO"
```

A few alternatives to create the same instance:

```
take('hello')->strtoupper()->get();

// "HELLO"

pipe('hello')->strtoupper()->get();

// "HELLO"
```

Of course that's not very useful since you could've just used `strtoupper('hello')` and be done with it, but the goal is to make multi-method calls on a value easier to read and write:

```
$subdomain = Pipe::from('https://blog.sebastiaanluca.com')
    ->parse_url()
    ->end()
    ->explode('.', PIPED_VALUE)
    ->reset()
    ->get();

// "blog"
```

Note that in comparison to the original RFC, there's no need to pass the initial value to methods that receive the value as first parameter and have no other required parameters. The previous value is always passed as first parameter. In effect, both of the following examples will work:

```
Pipe::from('hello')->strtoupper()->get();

// "HELLO"

Pipe::from('hello')->strtoupper(PIPED_VALUE)->get();

// "HELLO"
```

In contrast, if a method takes e.g. a setting before the previous value, we need to set it manually using the replacement identifier (the globally available `PIPED_VALUE` constant). This identifier can be placed *anywhere* in the method call, it will simply be replaced by the previous value.

```
Pipe::from(['key' => 'value'])
    ->array_search('value', PIPED_VALUE)
    ->get();

// "key"
```

### Using first class callable syntax (enabling IDE autocompletion)

[](#using-first-class-callable-syntax-enabling-ide-autocompletion)

Since PHP 8.1, you can use a first class callable syntax, or simply put an anonymous function, to pipe the value through. This enables **full method autocompletion**.

```
take('STRING')
    ->pipe(strtolower(...))
    ->get()

// "string"
```

Or using parameters:

```
Pipe::from('https://sebastiaanluca.com/blog')
    ->pipe(parse_url(...))
    ->end()
    ->pipe(substr(...), PIPED_VALUE, 3)
    ->pipe(strtoupper(...))
    ->get(),

// "OG"
```

### Using closures

[](#using-closures)

Sometimes standard methods don't cut it and you need to perform a custom operation on a value in the process. You can do so using a closure:

```
Pipe::from('string')
    ->pipe(fn(string $value): string => 'prefixed-' . $value)
    ->get();

// "prefixed-string"
```

### Using class methods

[](#using-class-methods)

The same is possible using a class method (regardless of visibility):

```
class MyClass
{
    public function __construct()
    {
        Pipe::from('HELLO')
            ->pipe($this)->lowercase()
            ->get();

        // "hello"
    }

    /**
     * @param string $value
     *
     * @return string
     */
    private function lowercase(string $value) : string
    {
        return mb_strtolower($value);
    }
}
```

#### Class method alternatives

[](#class-method-alternatives)

If you don't want to use the internal pipe proxy and pass `$this`, there are two other ways you can use class methods.

Using first class callable syntax:

```
class MyClass
{
    public function __construct()
    {
        Pipe::from('HELLO')
            ->pipe($this->lowercase(...))
            ->get();

        // "hello"
    }

    /**
     * @param string $value
     *
     * @return string
     */
    public function lowercase(string $value) : string
    {
        return mb_strtolower($value);
    }
}
```

Using an array (for public methods only):

```
class MyClass
{
    public function __construct()
    {
        Pipe::from('HELLO')
            ->pipe([$this, 'lowercase'])
            ->get();

        // "hello"
    }

    /**
     * @param string $value
     *
     * @return string
     */
    public function lowercase(string $value) : string
    {
        return mb_strtolower($value);
    }
}
```

By parsing the callable method to a closure:

```
use Closure;

class MyClass
{
    public function __construct()
    {
        Pipe::from('HELLO')
            ->pipe(Closure::fromCallable([$this, 'lowercase']))
            ->get();

        // "hello"
    }

    /**
     * @param string $value
     *
     * @return string
     */
    private function lowercase(string $value) : string
    {
        return mb_strtolower($value);
    }
}
```

What does it solve?
-------------------

[](#what-does-it-solve)

This package is based on the [pipe operator RFC by Sara Golemon (2016)](https://wiki.php.net/rfc/pipe-operator), who explains the problem as:

> A common PHP OOP pattern is the use of method chaining, or what is also known as “Fluent Expressions”. \[…\] This works well enough for OOP classes which were designed for fluent calling, however it is impossible, or at least unnecessarily arduous, to adapt non-fluent classes to this usage style, harder still for functional interfaces.

Coming across the proposal, I also [blogged about it](https://sebastiaanluca.com/blog/enabling-php-method-chaining-with-a-makeshift-pipe-operator).

### A simple example

[](#a-simple-example)

Say you want to get the subdomain from a URL, you end up with something like this:

```
$subdomain = 'https://blog.sebastiaanluca.com/';
$subdomain = parse_url($subdomain, PHP_URL_HOST);
$subdomain = explode('.', $subdomain);
$subdomain = reset($subdomain);

// "blog"
```

This works, of course, but it's quite verbose and repetitive.

### Another way of writing

[](#another-way-of-writing)

Same result, different style:

```
$subdomain = explode('.', parse_url('https://blog.sebastiaanluca.com/', PHP_URL_HOST))[0];

// "blog"
```

This might be the worst of all solutions, as it requires you to start reading from the center, work your way towards the outer methods, and keep switching back and forth. The more methods and variants, the more difficult to get a sense of what's going on.

### More examples of the issue at hand

[](#more-examples-of-the-issue-at-hand)

See [Sara's RFC](https://wiki.php.net/rfc/pipe-operator#introduction) for more complex and real-world examples.

Notes
-----

[](#notes)

While this packages makes a good attempt at bringing the pipe operator to PHP, it unfortunately does not offer autocompletion on chained methods. For that to work we need the real deal, so make some noise and get the people in charge to vote *for* Sara's RFC!

License
-------

[](#license)

This package operates under the MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.

Change log
----------

[](#change-log)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Testing
-------

[](#testing)

```
composer install
composer test
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Sebastiaan Luca](https://github.com/sebastiaanluca)
- [All Contributors](../../contributors)

About
-----

[](#about)

My name is Sebastiaan and I'm a freelance back-end developer specializing in building custom Laravel web apps. Check out my [website](https://sebastiaanluca.com) for more information and my other [packages](https://packagist.org/packages/sebastiaanluca) to kick-start your next project.

Have a project that could use some guidance? Send me an e-mail at !

###  Health Score

55

—

FairBetter than 98% of packages

Maintenance42

Moderate activity, may be stable

Popularity51

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity86

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 98.1% 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 ~231 days

Recently: every ~264 days

Total

12

Last Release

465d ago

Major Versions

2.1.1 → 3.0.02019-02-27

3.0.1 → 4.0.02021-06-22

4.0.0 → 5.0.02022-03-17

5.1.0 → 6.0.02023-02-06

6.0.0 → 7.0.02025-02-07

PHP version history (7 changes)1.0.0PHP ^7.1

3.0.0PHP ^7.2

4.0.0PHP ^8

5.0.0PHP ~8.0|~8.1

5.1.0PHP ~8.1

6.0.0PHP ~8.1|~8.2

7.0.0PHP ^8.3.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/711940?v=4)[Sebastiaan Luca](/maintainers/sebastiaanluca)[@sebastiaanluca](https://github.com/sebastiaanluca)

---

Top Contributors

[![sebastiaanluca](https://avatars.githubusercontent.com/u/711940?v=4)](https://github.com/sebastiaanluca "sebastiaanluca (103 commits)")[![imliam](https://avatars.githubusercontent.com/u/4326337?v=4)](https://github.com/imliam "imliam (1 commits)")[![JosephSilber](https://avatars.githubusercontent.com/u/1403741?v=4)](https://github.com/JosephSilber "JosephSilber (1 commits)")

---

Tags

chainmethodoperatorphppiperfctakephppipeoperatortake

###  Code Quality

TestsPHPUnit

Static AnalysisRector

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/sebastiaanluca-php-pipe-operator/health.svg)

```
[![Health](https://phpackages.com/badges/sebastiaanluca-php-pipe-operator/health.svg)](https://phpackages.com/packages/sebastiaanluca-php-pipe-operator)
```

###  Alternatives

[imanghafoori/laravel-anypass

A minimal yet powerful package to help you in development.

21421.6k](/packages/imanghafoori-laravel-anypass)[transprime-research/piper

PHP Pipe method execution with values from chained method executions

174.6k2](/packages/transprime-research-piper)

PHPackages © 2026

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