Мой Telegram-канал с материалами по PHP и архитектуре: https://t.me/berloga_aiti
В версии PHP 8.5 появился оператор |> — так называемый pipe operator. Он давно используется в других языках (F#, Elixir, OCaml) и активно применяется в JavaScript. Его основная цель — упростить передачу результата одной операции в следующую, делая код более читаемым и линейным.
В этой статье рассмотрим историю появления оператора, его устройство, корректные способы использования, типичные ошибки и рекомендации.
Историческая справка
Идея оператора «передай дальше» появилась в функциональных языках ещё в 1990-х. Например, в F# оператор |> стал одним из ключевых механизмов функционального стиля. Позднее схожий подход начали применять в JavaScript.
Для PHP обсуждение pipe-оператора началось в 2021 году. Первые RFC предлагали реализацию, аналогичную JavaScript:
value |> fn($x) => ...
Однако обсуждение затягивалось, так как PHP должен был сохранить обратную совместимость и учесть существующие правила вызова функций. В результате к 2024 году родился более аккуратный и предсказуемый вариант — тот, что вошёл в PHP 8.5.
Главное свойство оператора - он подставляет результат слева как первый аргумент функции справа.

Базовый принцип работы
$x |> f()
эквивалентно вызову:
f($x);
Механизм работает для:
глобальных функций;
методов объектов (через замыкания);
любых замыканий и стрелочных функций.
Правила использования правой части |>
В левой части оператора |> может находиться произвольное значение или выражение. В правой части должно быть допустимое callable-выражение, которое принимает единственный параметр.
Основные ограничения:
-
Функции с двумя и более обязательными параметрами запрещены.
Если попытаться вызвать такую функцию через pipe, PHP выдаст ошибку, как при стандартном вызове с недостаточным количеством аргументов:function add($a, $b) { return $a + $b; } $result = 5 |> add(); // Ошибка: недостаточно аргументов -
Нельзя передавать функции с аргументами по ссылке.
PHP выбросит ошибку, если функция в правой части принимает переменную по ссылке:function increment(&$x) { $x++; } $value = 10; $value |> increment(); // Ошибка -
В правой части должно быть вызываемое значение (callable).
Если передать что-то, что не является функцией или замыканием, PHP выдаст Error:$value = 5; $value |> 123; // Ошибка: 123 не является callable -
Стрелочные функции в цепочке требуют круглых скобок (из-за синтаксической двусмысленности):
$value |> (fn($x) => $x + 1) |> (fn($y) => $y * 2);
Примеры использования
Получение длины строки
$size = 'Welcome to PHP!' |> strlen();
Обработка строки
$message
|> trim()
|> strtolower()
|> ucwords();
Работа с массивами
$products
|> (fn($items) => array_column($items, 'categories'))
|> (fn($lists) => array_merge(...$lists))
|> array_unique()
|> array_values();
Бизнес-логика в виде цепочки
$employees
|> array_filter(fn($emp) => $emp['salary'] > 48000)
|> array_map(fn($emp) => $emp['name'])
|> implode(', ');
Типичные ошибки и их причины
Ошибка №1. Функция не принимает аргументов
$value |> decodeJson(); // Ошибка: Too many arguments
Решение:
$value |> (fn($x) => decodeJson($x));
или если аргументы не нужны:
$value |> (fn() => decodeJson());
Ошибка №2. Неверный порядок аргументов функции
$value |> preg_match('/test/'); // Не соответствует порядку аргументов
Решение:
$value |> (fn($x) => preg_match('/test/', $x));
Ошибка №3. Метод объекта нельзя вызвать напрямую
$user |> $service->process(); // PHP интерпретирует как $service->process($user)
Правильно:
$user |> (fn($x) => $service->process($x));
Ошибка №4. Неправильное использование с конструкторами
$data |> new DTO(); // PHP вызовет new DTO($data)
Корректно:
$data |> (fn($x) => new DTO($x));
Ошибка №5. Пайп там, где ухудшает читаемость
Pipe operator удобен для длинных цепочек преобразований, но для простых или атомарных вызовов лучше оставить классический вызов.
Рекомендации по использованию
Использовать pipe для многошаговых преобразований.
Для функций с аргументами в «неподходящем» порядке — применять лямбды.
Не превращать каждую операцию в pipe; стиль важнее моды.
При сомнениях в сигнатуре функции — оборачивать в замыкание.
Стрелочные функции в пайпах обязательно заключать в круглые скобки, если они участвуют в цепочке.
Взгляд в будущее
Появление pipe operator в PHP 8.5 - это первый шаг к более функциональному стилю программирования. В ближайших версиях ожидается развитие:
Partial application (частичное применение функций);
Композиция функций;
Улучшение поддержки чистых функций в PHP.
Это позволит писать код, более похожий на F# или Elixir, где цепочки преобразований становятся естественным инструментом.
Заключение
Pipe operator делает PHP более современным, облегчает чтение и поддержку кода.
Главное - правильно использовать его с учётом аргументов функций и методов, не превращать побочные эффекты в пайпы и использовать лямбды с контролем порядка аргументов.
Мой Telegram-канал с материалами по PHP и архитектуре: https://t.me/berloga_ait
Комментарии (10)

Rsa97
09.12.2025 17:15Вот только узнавать всё лучше в официальной документации.
А тут все примеры нерабочие, в вызове функций должен стоять spread-оператор.$ php -r '$size = "Welcome to PHP!" |> strlen(); print $size;' PHP Fatal error: Uncaught ArgumentCountError: strlen() expects exactly 1 argument, 0 given in Command line code:1 $ php -r '$size = "Welcome to PHP!" |> strlen(...); print $size;' 15Ну и якобы ошибки:
1, 3, 4 - пропущен spread. Если его поставить, то всё работает без дополнительного оборачивания в лямбду;
2 - у preg_match два обязательных аргумента, а в пайпе разрешены только функции с одним обязательным аргументом.

positroid
09.12.2025 17:15Честно говоря по ошибкам ничего не понятно, то ли примеры кривые, то ли комментарии.
$value |> decodeJson(); // Ошибка: Too many arguments$value |> (fn($x) => decodeJson($x)); // решениеВ чем решение, если внутри все также передаем в функцию атрибут? Записи равнозначны и ошибка должна быть такой же. К тому же если функция не принимает атрибутов - в чем смысл использовать с ней пайп?
$user |> $service->process(); // PHP интерпретирует как $service->process($user)В комментарии ожидаемое на первый взгляд поведение, но это неверно же. PHP сначала выполнит
$service->process();и дальше либо упадет из-за не переданного обязательного аргумента, либо упадет из-за того что process не вернул callable с 1 аргументом, либо отработает, если результат process() - callable с единственным обязательным аргументом.$data |>newDTO(); // PHP вызовет new DTO($data)Это вариация прошлой ошибки, но PHP вызовет new DTO() - без передачи аргумента.
Сильно сбивает с толку.

kisandiv Автор
09.12.2025 17:15Данные примеры из реальной жизни.
Это предостережения для вас читателей.
Как лучше не стоит не делать.
Код в данных участках сильно подвержен изменениям.
Скорее всего в какой-то момент расширится конструктор или набор входных аргументов.
Что в будущем может спровоцировать ошибки.
Именно в таких местах: конструкторы, методы объекта, наши кастомные функции.
Поэтому pipe лучше следует применять к функциям, которые "редко меняются" или по умолчанию просто оборачивать в анонимные функции, чтобы не спровоцировать ошибки

Rsa97
09.12.2025 17:15Если изменится сигнатура вызова, например, то у вас хоть вызов через пайп, хоть прямой, всё равно дадут ошибку. Ну или приведите пример обратного. Только потрудитесь свои примеры проверять, а не от балды их писать, как в статье.

Rsa97
09.12.2025 17:15Тут вся статья кривая. Если сделать как полагается, то всё работает без лямбд,
$value |> decodeJson(...); $user |> $service->process(...); $data |> new DTO(...);

bolk
09.12.2025 17:15Реально кривая статья. ИИ что ли писал? Как верно заметили выше, вместо обёрток надо использовать создание замыканий через многоточие.
Кстати, теперь у нас есть ещё и функция clone:php -r 'var_dump((object) [] |> clone(...));'
object(stdClass)#2 (0) {
}
Rsa97
09.12.2025 17:15clone был и раньше. Сейчас его расширили, добавив второй параметр - ассоциативный массив со свойствами, которые будут изменены в копии. Это позволяет менять readonly-свойства при копировании.
kamentim
Классная статья, прям то, чего не хватало по пайпам в новой версии пыхи. Не просто «вот новый синтаксис», а с акцентом на подводные камни и реальные ограничения, из-за которых легко наломать дров в проде. Нравится, что ты не агитируешь «тащить pipe везде», а честно пишешь, где он ухудшает читаемость и когда без замыканий лучше не лезть. Одним словом контент топ, давай еще статей)
positroid
Ну очевидный ИИшный бот же. Вот зачем? Ради продвижения канала?
kamentim
кОпец даже не знаю комплимент или оскорбление