<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maksim Epikhin</title>
    <description>The latest articles on DEV Community by Maksim Epikhin (@maksimepikhin).</description>
    <link>https://dev.to/maksimepikhin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F519754%2Fdc228692-a305-4384-85c3-c0b20efd984d.jpg</url>
      <title>DEV Community: Maksim Epikhin</title>
      <link>https://dev.to/maksimepikhin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maksimepikhin"/>
    <language>en</language>
    <item>
      <title>The Laravel Idea Plugin is Now Free for PhpStorm Users</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Thu, 31 Jul 2025 08:13:56 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/the-laravel-idea-plugin-is-now-free-for-phpstorm-users-74n</link>
      <guid>https://dev.to/maksimepikhin/the-laravel-idea-plugin-is-now-free-for-phpstorm-users-74n</guid>
      <description>&lt;p&gt;Starting July 30, 2025, the &lt;strong&gt;&lt;a href="https://laravel-idea.com/" rel="noopener noreferrer"&gt;Laravel Idea plugin&lt;/a&gt;&lt;/strong&gt; will be &lt;strong&gt;free for PhpStorm users&lt;/strong&gt;. If you already have it installed, you’ll get &lt;strong&gt;full access to all features&lt;/strong&gt; at no extra cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laravel Idea&lt;/strong&gt; is a smart Laravel development environment built on PhpStorm. Developed by Adel Faizrakhmanov, the plugin has been downloaded over 1.5 million times from the JetBrains Marketplace and is highly regarded by Laravel developers. It enhances PhpStorm’s native Laravel support with powerful productivity-boosting tools, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent code generation.&lt;/li&gt;
&lt;li&gt;Advanced autocompletion for routes, validation, request fields, policies, configs, translations, views, and more.&lt;/li&gt;
&lt;li&gt;Deep Eloquent ORM understanding.&lt;/li&gt;
&lt;li&gt;Full Blade component support.&lt;/li&gt;
&lt;li&gt;Seamless integration with Livewire, Inertia.js, Dusk, Laravel Modules, and other third-party packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqezcnsytgbizsgv74brs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqezcnsytgbizsgv74brs.png" alt=" " width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To install the Laravel Idea plugin in PhpStorm, go to Settings | Plugins and search for the plugin in the Marketplace tab.&lt;/p&gt;

&lt;p&gt;Source link: &lt;a href="https://blog.jetbrains.com/phpstorm/2025/07/laravel-idea-is-now-free/?_cl=MTsxOzE7dlkyeWZyYlVLUWpJS0RISmkwSnNrMWFmZHp6QUZiMHkyN2R5bW1mdHN3Q2RrR3dpUG1INlM0MGVTTEg1dzhzcjs=" rel="noopener noreferrer"&gt;The Laravel Idea Plugin is Now Free for PhpStorm Users&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>news</category>
      <category>php</category>
      <category>laravel</category>
    </item>
    <item>
      <title>PHP 8.5: New array functions. array_first() and array_last()</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Sun, 06 Jul 2025 21:23:01 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/php-85-new-array-functions-arrayfirst-and-arraylast-1j9j</link>
      <guid>https://dev.to/maksimepikhin/php-85-new-array-functions-arrayfirst-and-arraylast-1j9j</guid>
      <description>&lt;h1&gt;
  
  
  PHP RFC: array_first() and array_last()
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Version: 1.0&lt;/li&gt;
&lt;li&gt;Date: 2025-03-31&lt;/li&gt;
&lt;li&gt;Author: Niels Dossche, &lt;a href="mailto:nielsdos@php.net"&gt;nielsdos@php.net&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Status: Implemented&lt;/li&gt;
&lt;li&gt;Target Version: 8.5&lt;/li&gt;
&lt;li&gt;Implementation: &lt;a href="https://github.com/php/php-src/commit/168343d2e811fe0f2152d39a8f88557cc0b35c86" rel="noopener noreferrer"&gt;https://github.com/php/php-src/commit/168343d2e811fe0f2152d39a8f88557cc0b35c86&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;First Published at: &lt;a href="https://wiki.php.net/rfc/array_first_last" rel="noopener noreferrer"&gt;https://wiki.php.net/rfc/array_first_last&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In PHP 7.3, we got array_key_first() and array_key_last() to get the first and last keys from an array. What we don't have yet is a way to get the first and last values of an array. This is harder than you may think because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The array keys are not necessarily integers, not necessarily starting with 0, etc...&lt;/li&gt;
&lt;li&gt;Existing "tricks" like reset() and end() are semantically the wrong approach because they modify the "internal iterator" of the array. Furthermore, it also does not work properly on all types of expressions (e.g. an array returned from a function / plain array can cause a notice due to the by-ref argument).&lt;/li&gt;
&lt;li&gt;Using ''$array[array_key_first($array)]'' is cumbersome&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Proposal
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;array_first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;array_last&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These functions return the first/last value of the array, respectively. I.e. these functions are equivalent to ''$array[array_key_first($array)]'' and similarly for the last element. Alternatively, for array_first(), this could be written as a foreach loop where the first iteration returns.&lt;/p&gt;

&lt;p&gt;If the array value to be returned is a reference, it is dereferenced automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Behaviour on empty arrays
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.toThe%20RFC%20introducing%20the%20key%20functions"&gt;https://wiki.php.net/rfc/array_key_first_last&lt;/a&gt; also proposed to implement these functions, but the vote for those failed. The main complaint seemed to be the behaviour on failure.&lt;/p&gt;

&lt;p&gt;Should it throw on an empty array or should it return NULL?&lt;br&gt;
Theoretically NULL can be a valid value from an array, and therefore returning NULL does not allow distinguishing between an empty array and a NULL value. However, there are still strong arguments in favor of using NULL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent with ''$array[array_key_first($array)]'', i.e. accessing a non-existent key gives NULL&lt;/li&gt;
&lt;li&gt;Consistent with ''array_find($arr, fn () =&amp;gt; true)'' returning NULL on no match&lt;/li&gt;
&lt;li&gt;Consistent with ''array_shift()'' and ''array_pop()'' returning NULL on empty arrays (also about retrieving first/last element, but with modification)&lt;/li&gt;
&lt;li&gt;Consistent with common framework helpers like ''Arr::first()''&lt;/li&gt;
&lt;li&gt;NULL is a rare legitimate value, so the potential for clashing is low&lt;/li&gt;
&lt;li&gt;Works nicely with "??" operator&lt;/li&gt;
&lt;li&gt;If it were to throw an exception instead, then you would need to check the size of the array upfront. Similarly, if NULL is a legit value then you can just check the array size upfront too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another interesting idea is to add an optional "$default" argument (i.e. if provided return the default; otherwise throw). However, since PHP arrays are untyped it's often hard to define something meaningful as a sentinel value. There is also no precedent for this design choice for the array functions. Furthermore, when a programmer reads ''array_first($somevar, $someothervar)'', it looks weird unless you already know that ''$somevar'' is an array and ''$someothervar'' is a fallback value. It just looks unintuitive.&lt;/p&gt;
&lt;h3&gt;
  
  
  Naming
&lt;/h3&gt;

&lt;p&gt;Why array_first/array_last instead of array_value_first/array_value_last?&lt;br&gt;
First, this is consistent with how (most) array functions are named: the ones that work on keys have "key" in the name, and the ones that work on values don't have "value" in the name. Think about array_find, array_find_key, etc.&lt;br&gt;
Second, the shorter name is less verbose and intuitively at least I understood this is about the value.&lt;/p&gt;
&lt;h3&gt;
  
  
  Fibers
&lt;/h3&gt;

&lt;p&gt;In the &lt;a href="https://dev.todiscussion%20thread%20from%202023"&gt;https://externals.io/message/121313&lt;/a&gt; there was some confusion on how this interacted with Fibers. TL;DR: The concern was that if you have a call for array_key_first() followed by array_first() that the result could be inconsistent if a Fiber interrupted the execution. This is however based on the false premise that Fibers are threads, in fact they are not. This situation cannot happen.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why include this in the engine rather than userland?
&lt;/h3&gt;

&lt;p&gt;Three main reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistency with array_key_first()/array_key_last().&lt;/li&gt;
&lt;li&gt;The cost/maintenance burden is practically zero, the implementation is stupidly simple (4 lines trivial argument parsing boilerplate, 3 lines actual code; per function).&lt;/li&gt;
&lt;li&gt;Very fast implementation, faster than a PHP implementation in my brief tests. Further optimization is possible by implementing an additional frameless variant, but that's future material if ever necessary/interesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Here are some code examples of how to use these functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;array_first&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"single element"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "single element"&lt;/span&gt;
&lt;span class="nf"&gt;array_last&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"single element"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "single element"&lt;/span&gt;

&lt;span class="nf"&gt;array_first&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// NULL&lt;/span&gt;
&lt;span class="nf"&gt;array_last&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// NULL&lt;/span&gt;

&lt;span class="nf"&gt;array_first&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 'a'&lt;/span&gt;
&lt;span class="nf"&gt;array_last&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 'd'&lt;/span&gt;

&lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;array_first&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "hello" (no ref)&lt;/span&gt;
&lt;span class="nf"&gt;array_last&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "hello" (no ref)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backward Incompatible Changes
&lt;/h2&gt;

&lt;p&gt;If anyone defined array_first() or array_last() in their global scope, then they need to guard it now with function_exists or throw it away because of the name clash. Although it should be noted that the global namespace is normally reserved for PHP's usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposed PHP Version(s)
&lt;/h2&gt;

&lt;p&gt;Next PHP 8.x, i.e. PHP 8.5 at the time of writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patches and Tests
&lt;/h2&gt;

&lt;p&gt;PR: &lt;a href="https://github.com/php/php-src/pull/18210" rel="noopener noreferrer"&gt;https://github.com/php/php-src/pull/18210&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;After the project is implemented, this section should contain &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the version(s) it was merged into: 8.5&lt;/li&gt;
&lt;li&gt;a link to the git commit(s): &lt;a href="https://github.com/php/php-src/commit/168343d2e811fe0f2152d39a8f88557cc0b35c86" rel="noopener noreferrer"&gt;https://github.com/php/php-src/commit/168343d2e811fe0f2152d39a8f88557cc0b35c86&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;a link to the PHP manual entry for the feature: TBD&lt;/li&gt;
&lt;li&gt;a link to the language specification section (if any): N/A&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Current discussion: &lt;a href="https://externals.io/message/127047" rel="noopener noreferrer"&gt;https://externals.io/message/127047&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prior Work
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Proposal from 2023 discussing these new functions: &lt;a href="https://externals.io/message/121313" rel="noopener noreferrer"&gt;https://externals.io/message/121313&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RFC that introduced array_key_first() and array_key_last(): &lt;a href="https://wiki.php.net/rfc/array_key_first_last" rel="noopener noreferrer"&gt;https://wiki.php.net/rfc/array_key_first_last&lt;/a&gt; with discussion: &lt;a href="https://externals.io/message/102663" rel="noopener noreferrer"&gt;https://externals.io/message/102663&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>PHP 8.5 Pipe operator v3</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Fri, 04 Jul 2025 09:19:01 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/php-85-pipe-operator-v3-42ob</link>
      <guid>https://dev.to/maksimepikhin/php-85-pipe-operator-v3-42ob</guid>
      <description>&lt;h1&gt;
  
  
  PHP &lt;a href="https://wiki.php.net/rfc/" rel="noopener noreferrer"&gt;https://wiki.php.net/rfc/&lt;/a&gt; Pipe operator v3
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Version: 0.9&lt;/li&gt;
&lt;li&gt;Date: 2025-02-05&lt;/li&gt;
&lt;li&gt;Author: Larry Garfield (&lt;a href="mailto:larry@garfieldtech.com"&gt;larry@garfieldtech.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Status: Implemented&lt;/li&gt;
&lt;li&gt;Target version: PHP 8.5&lt;/li&gt;
&lt;li&gt;First Published at: &lt;a href="http://wiki.php.net/rfc/pipe-operator-v3" rel="noopener noreferrer"&gt;http://wiki.php.net/rfc/pipe-operator-v3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementation: &lt;a href="https://github.com/php/php-src/commit/1c09c0c8323342aaaecbe444b3afa45efbd72ced" rel="noopener noreferrer"&gt;https://github.com/php/php-src/commit/1c09c0c8323342aaaecbe444b3afa45efbd72ced&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In object-oriented code, "composition" generally means "one object having a reference to another."  In functional programming, "composition" generally means "sticking two functions together end-to-end to make a new function."  Both are valid and useful techniques, especially in a multi-paradigm language like PHP.&lt;/p&gt;

&lt;p&gt;Composition generally takes two forms: Immediate and delayed.  The immediate execution of chained functions is typically implemented with a "pipe" operator.  Delayed execution is typically implemented with a composition operator, which takes two functions and produces a new function that will call each one in turn.  The combination of the two cleanly enables “point-free style,” an approach to programming that limits the use of unnecessary intermediary variables. Point-free style has been gaining popularity in JavaScript circles, so will be familiar to JavaScript developers using that style. &lt;/p&gt;

&lt;p&gt;This RFC introduces the "pipe" operator, in the form used by most other languages with such functionality.  A &lt;a href="https://wiki.php.net/rfc/function-composition" rel="noopener noreferrer"&gt;function composition operator&lt;/a&gt; is saved for a follow up RFC.  (See Future Scope.)&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isAdmin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'john.doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isAdmin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This is the new syntax.&lt;/span&gt;
&lt;span class="nv"&gt;$numberOfAdmins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$numberOfAdmins&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(1);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Proposal
&lt;/h1&gt;

&lt;p&gt;This RFC introduces a new operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;mixed&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ''|&amp;gt;'' operator, or "pipe," accepts a single-parameter callable on the right and passes the left-side value to it, evaluating to the callable's result.&lt;/p&gt;

&lt;p&gt;Pipe (''|&amp;gt;'') evaluates left to right by passing the value (or expression result) on the left as the first and only parameter to the callable on the right.  That is, the following two code fragments are logically equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a single call that is not especially useful.  It becomes useful when multiple calls are chained together.  That is, the following two code fragments are effectively equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;htmlentities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strtoupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;htmlentities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strtoupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The left-hand side of the pipe may be any value or expression.  The right-hand side may be any valid PHP callable that takes a single parameter, or any expression that evaluates to such a callable.  Functions with more than one required parameter are not allowed and will fail as if the function were called normally with insufficient arguments.  If the right-hand side does not evaluate to a valid callable it will throw an Error.&lt;/p&gt;

&lt;p&gt;A pipe chain is an expression, and therefore may be used anywhere an expression is valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Precedence
&lt;/h2&gt;

&lt;p&gt;The pipe operator is left-associative.  The left side will be evaluated first, before the right side.&lt;/p&gt;

&lt;p&gt;The pipe operator precedence has been selected around expected common use cases.  In particular, it binds before comparison operations so that its result may be compared, but after mathematical operations.  If appropriate, parentheses can be added around any set of operations to alter or clarify the precedence, just like any other expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// These are equivalent.&lt;/span&gt;
&lt;span class="nv"&gt;$res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt;  &lt;span class="nf"&gt;someFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt;  &lt;span class="nf"&gt;someFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The result of the pipe chain is compared against 4.&lt;/span&gt;
&lt;span class="nv"&gt;$res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'beep'&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The pipe executes before the ??, so the &lt;/span&gt;
&lt;span class="c1"&gt;// default value applies to the result of the whole chain.&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;
     &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;get_username&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This requires parens&lt;/span&gt;
&lt;span class="nv"&gt;$res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user_specified_func&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nf"&gt;defaultFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// This requires parens to allow the &lt;/span&gt;
&lt;span class="c1"&gt;// ternary to run first and select the callable to use.&lt;/span&gt;
&lt;span class="nv"&gt;$res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'flag'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;enabledFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;disabledFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;The current implementation works entirely at the compiler level, and effectively transforms the first example above into the second at compile time.  The result is that pipe itself has virtually no runtime overhead.  (Any additional closures created by the user while writing a pipe will of course have their own overhead.)&lt;/p&gt;

&lt;p&gt;More precisely, the implementation contains 3 optimizations, for a function-style, method-style, or static method style first-class-callable.  Those will be compiled down to direct calls, and therefore have no performance overhead.  An arbitrary expression will be evaluated and then executed, with no additional overhead.  However, that arbitrary expression may have additional logic in it to support a pipe that cannot be compiled away.  For example, an inline arrow function that simply forwards the call is not detectable, so the extra arrow function cannot be optimized away.&lt;/p&gt;

&lt;p&gt;That means the above example would more precisely compile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;htmlentities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strtoupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives a little overhead over making all calls directly, but only in some cases, and not dramatically so.&lt;/p&gt;

&lt;p&gt;Should the proposed follow-up RFC of &lt;a href="https://wiki.php.net/rfc/partial_function_application" rel="noopener noreferrer"&gt;Partial Function Application RFC&lt;/a&gt; (see below) be approved, it would be logical and recommended for a similar optimization to be made when a PFA appears on the right-side of pipe.  That would eliminate most common uses of a wrapping closure as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Callable styles
&lt;/h2&gt;

&lt;p&gt;Pipe supports any callable syntax supported by PHP.  At present, the most common form is first-class-callables (eg, ''strlen(...)''), which dovetails with this syntax very cleanly.  Should further improvements be made in the future, such as a revised &lt;a href="https://wiki.php.net/rfc/partial_function_application" rel="noopener noreferrer"&gt;Partial Function Application RFC&lt;/a&gt;, it would be supported naturally.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;As usual, references are an issue.  Supporting pass-by-ref parameters in simple cases is quite easy, and a naive implementation would support it.  However, passing a value from a compound value (an object property or array element) by reference does not work, and throws an "Argument could not be passed by reference" error.  In practice, it is easier to forbid pass-by-ref parameters in pipe than to allow them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'C'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;inc_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This can be made to work.&lt;/span&gt;
&lt;span class="nv"&gt;$val&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inc_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This cannot be easily made to work, and it might not even be possible.&lt;/span&gt;
&lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inc_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is also consistent with the typical usage patterns.  The whole design of the pipe operator is that data flows through it from left to right, in pure-functional way.  Passing by reference would introduce all sorts of potential "spooky action at a distance."  In practice, there are few if any use cases where it would be appropriate to do in the first place.&lt;/p&gt;

&lt;p&gt;For that reason, pass-by-ref callables are disallowed on the right-hand side of a pipe operator.  That is, both examples above would error.&lt;/p&gt;

&lt;p&gt;One exception to this is "prefer-ref" functions, which only exist in the stdlib and cannot be implemented in user-space.  There are a small handful of functions that will accept either a reference or a direct value, and vary their behavior depending on which they get.  When those functions are used with the pipe operator, the value will be passed by value, and the function will behave accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax choice
&lt;/h2&gt;

&lt;p&gt;F#, &lt;a href="https://elixirschool.com/en/lessons/basics/pipe-operator/|Elixir]],%20and%20OCaml%20all%20use%20the%20''|&amp;gt;''%20operator%20already%20for%20this%20exact%20same%20behavior.%20%20There%20has%20been%20a%20long-standing%20[[https://github.com/tc39/proposal-pipeline-operator/wiki" rel="noopener noreferrer"&gt;discussion in JavaScript&lt;/a&gt; about adding a ''|&amp;gt;'' operator as described here.  It is the standard operator for this task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;p&gt;The use cases for a pipe operator are varied.  They include, among others, encouraging shallow-function-nesting, encouraging pure functions, expressing a complex process in a single expression, and emulating extension functions.&lt;/p&gt;

&lt;p&gt;The following examples are all simplified from real-world use cases in code I have written.&lt;/p&gt;

&lt;h3&gt;
  
  
  String manipulation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified version.  The original code this is&lt;/span&gt;
&lt;span class="c1"&gt;// based on splits a string at _ and capitals, too, but&lt;/span&gt;
&lt;span class="c1"&gt;// that is omitted to focus on the core point.&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;splitString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Convert a string to snake_case&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Fred Flintstone'&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;splitString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// Produces an array of individual words.&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Join those words with _&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;// Lowercase everything.&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// $result is 'fred_flintstone'&lt;/span&gt;

&lt;span class="c1"&gt;// Convert a string to lowerCamelCase&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Fred Flintstone'&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;splitString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Uppercase the first letter of each word&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="c1"&gt;// Join those words&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lcfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                           &lt;span class="c1"&gt;// Now lowercase just the first letter&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// $result is 'fredFlintstone'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Array combination
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tags'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Gets an array of arrays&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// Flatten that array into one big array&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                  &lt;span class="c1"&gt;// Remove duplicates&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                  &lt;span class="c1"&gt;// Reindex the array.&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// $result is ['a', 'b', 'c', 'd', 'e', 'x', 'y'. 'z']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The single-expression alternative today would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;array_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tags'&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which I believe is indisputably worse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shallow calls
&lt;/h3&gt;

&lt;p&gt;The use of a pipe for function composition also helps to separate closely related tasks so they can be developed and tested in isolation.  For a (slightly) contrived and simple example, consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loadWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Widget&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$ret&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Widget&lt;/span&gt;
    &lt;span class="c1"&gt;// Assume this is more complicated.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, it is impossible to test ''loadWidget()'' or ''loadMany()'' without also executing ''makeWidget()''.  While in this trivial example that's not a huge problem, in a more complex example it often is, especially if several functions/methods are nested more deeply.  Dependency injection cannot fully solve this problem, unless each step is in a separate injected class.&lt;/p&gt;

&lt;p&gt;By making it easy to chain functions together, however, that can be rebuilt like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loadWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"something else"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Widget&lt;/span&gt;
    &lt;span class="c1"&gt;// Assume this is more complicated.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$widgets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the latter could be further simplified with either a higher-order function or partial function application.  Those chains could also be wrapped up into their own functions/methods for trivial reuse.  They can also be extended, too.  For instance, the result of ''loadMany()'' is most likely going to be used in a ''foreach()'' loop.  That's a simple further step in the chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isOnSale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sellWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, because a pipe can take any callable, a pipe chain can be easily packaged up, either as a named function or anon function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This would be the "real" API that most code uses.&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loadSeveral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadSeveral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isOnSale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sellWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That neatly encapsulates the entire logic flow of a process in a clear, compact, highly-testable set of operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudo-extension functions
&lt;/h3&gt;

&lt;p&gt;"Extension functions" are a feature of Kotlin and C# (and possibly other languages) that allow for a function to act as though it is a method of another object.  It has only public-read access, but has the ergonomics of a method.  While not a perfect substitute, pipes do offer similar capability with a little more work.&lt;/p&gt;

&lt;p&gt;For instance, we could easily make utility higher-order functions (functions that take or return other functions/callables) that will map or filter an array that is piped to them.  (A more robust version that also handles iterables is only slightly more work.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;amap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;\Closure&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;afilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;\Closure&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That allows them to be used, via pipes, in a manner similar to "scalar methods."  To reuse the earlier example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadSeveral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;afilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isOnSale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;amap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sellWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is not far off from what it would look like with scalar methods, which still wouldn't work if any step along the way contained an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadSeveral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;afilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isOnSale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;amap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sellWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But can work with //any// value type, object or scalar.  It also entirely removes the "does the subject come first or last" question: the subject is //piped//, and the arguments to the higher-order function are the modifiers.  It also eliminates the need to discuss which methods deserve to be "first class" operations that turn into methods.  Any function can be chained onto a value of any type.&lt;/p&gt;

&lt;p&gt;While I do not believe pipes can completely replace extension functions, they provide a reasonable emulation and most of the benefits, for trivial cost.&lt;/p&gt;

&lt;p&gt;This RFC does not propose any such higher-order functions for the PHP standard library, as most are quite easy to implement in user space.  However, such could be easily added in the future if desired for especially common cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-expression pipelines
&lt;/h3&gt;

&lt;p&gt;Of particular note, all of the above examples are a single expression.  That makes them trivial to use in places where only a single-expression is allowed, such as ''match()'' arms, short-get property hooks, short-closures, etc.  For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="nv"&gt;$string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'something GoesHERE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$newString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$format&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'snake_case'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$string&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;splitString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'lowerCamel'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$string&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;splitString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lcfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// Other case options here.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BunchOfTags&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$widgets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$tags&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;widgets&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tags'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$loadSeveral&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;makeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Streams
&lt;/h3&gt;

&lt;p&gt;Similarly, a few small utility functions (either in C or PHP) would allow pipes to be used with stream resources.  As a simplified example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;decode_rot13&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;\Generator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nb"&gt;str_rot13&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Takes an iterable of strings and returns a line-buffering version of it.&lt;/span&gt;
&lt;span class="c1"&gt;// A more robust version is of course possible, but longer.&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;lines_from_charstream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;iterable&lt;/span&gt; &lt;span class="nv"&gt;$it&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;\Closure&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$it&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$buffer&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nv"&gt;$buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pipes.md'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// No variable, so it will close automatically when GCed.&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;decode_rot13&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;lines_from_charstream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str_getcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just a demonstration of the potential, not a recommendation for a specific API.  But hopefully it shows the potential for making working with streams in a structured way vastly easier, in a way found in a number of languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Existing implementations
&lt;/h2&gt;

&lt;p&gt;Multiple user-space libraries exist in PHP that attempt to replicate pipe-like or compose-like behavior.  All are clunky and complex by necessity compared to a native solution.  There is clear demand for this functionality, but user-space's ability to provide it is currently limited.  This list has only grown since the Pipes v2 RFC, indicating an even stronger benefit to the PHP ecosystem with a solid built-in composition syntax.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The PHP League has a &lt;a href="https://pipeline.thephpleague.com/" rel="noopener noreferrer"&gt;Pipeline&lt;/a&gt; library that encourages wrapping all functions into classes with an ''%%__invoke()%%'' method to allow them to be referenced, and using a ''-&amp;gt;pipe()'' call for each step.&lt;/li&gt;
&lt;li&gt;Laravel includes a &lt;a href="https://github.com/illuminate/pipeline|Illuminate/Pipeline]]%20package%20that%20has%20an%20[[https://agoalofalife.medium.com/pipeline-and-php-d9bb0a6370ca" rel="noopener noreferrer"&gt;even more cumbersome syntax&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/azjezz/psl|PHP%20Standard%20Library]]%20(PSL)%20library%20includes%20a%20[[https://github.com/azjezz/psl/blob/1.8.x/src/Psl/Fun/pipe.php" rel="noopener noreferrer"&gt;pipe function&lt;/a&gt;, though it is more of a function concatenation operation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sebastiaanluca/php-pipe-operator" rel="noopener noreferrer"&gt;Sebastiaan Luca&lt;/a&gt; has a pipe library that works through abuse of the ''%%__call%%'' method.  It only works for named functions, I believe, not for arbitrary callables.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Toobo/PipePie" rel="noopener noreferrer"&gt;PipePie&lt;/a&gt; is another very similar implementation to the previous ones.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dynamik-dev/zenpipe-php" rel="noopener noreferrer"&gt;ZenPipe&lt;/a&gt; is a new-comer that also uses a method named ''pipe()'' for what is actually a composition operation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Crell/fp" rel="noopener noreferrer"&gt;Crell/fp&lt;/a&gt; provides ''pipe()'' and ''compose()'' functions that take an array of callables.  While the lightest-weight option on this list, that makes dynamically-built pipelines or compositions more cumbersome than the syntax proposed here.&lt;/li&gt;
&lt;li&gt;Various blogs speak of "the Pipeline Pattern" (&lt;a href="https://medium.com/@aaronweatherall/the-pipeline-pattern-for-fun-and-profit-9b5f43a98130" rel="noopener noreferrer"&gt;for example&lt;/a&gt;), or more recently, &lt;a href="https://refactorers-journal.ghost.io/creating-a-type-safe-pipe-in-php/" rel="noopener noreferrer"&gt;Creating a type-safe pipe() in PHP&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those libraries would be mostly obsoleted by this RFC (in combination with the compose follow on, as noted in future-scope), with a more compact, more universal, better-performing syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why in the engine?
&lt;/h2&gt;

&lt;p&gt;The biggest limitation of any user-space implementation is performance.  Even the most minimal implementation (Crell/fp) requires adding 2-3 function calls to every operation, which is relatively expensive in PHP.  A native implementation would not have that additional overhead.  Crell/fp also results in somewhat awkward function nesting, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$someVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;htmlentities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;str_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strtoupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// (Or worse if you need conditional stages.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compared to the compiled version, this has two extra wrapping closures (for ''htmlentities()'' and ''str_split()'') that could not be compiled away, the call to ''pipe()'' itself, and a foreach loop inside pipe.  All of those are eliminated with a native operator.  As noted above, PFA would also allow eliminating the two manual closures via compiler optimization, something a user-space implementation would never be able to do.&lt;/p&gt;

&lt;p&gt;More elaborate implementations tend to involve magic methods (which are substantially slower than normal function/method calls) or multi-layer middlewares, which are severe overkill for sticking two functions together.&lt;/p&gt;

&lt;p&gt;Additionally, a native operator would make it much easier for static analysis tools to ensure compatible types.  The SA tools would know the input value's type, in most cases the callable type on the RHS, and could compare them directly without several layers of obfuscated user-space function calls between them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Future Scope
&lt;/h1&gt;

&lt;p&gt;This RFC is deliberately "step 1" of several closely related features to make composition-based code easier and more ergonomic.  It offers benefit on its own, but deliberately dovetails with several other features that are worthy of their own RFCs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Language features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A &lt;a href="https://wiki.php.net/rfc/function-composition" rel="noopener noreferrer"&gt;compose operator&lt;/a&gt;&lt;/strong&gt; for closures (likely ''+'').  Where pipe executes immediately, compose creates a new callable (Closure) that composes two or more other Closures.  That allows a new operation to be defined simply and easily and then saved for later in a variable.  Because it is "just" an operator, it is compatible with all other language features.  That means, for example, conditionally building up a pipeline is just a matter of throwing ''if'' statements around as appropriate.  The author firmly believes that a compose operator is a necessary companion to pipe, and the functionality will be incomplete without it.  However, while pipe can be implemented trivially in the compile step, a compose operator will require non-trivial runtime work.  For that reason it has been split out to its own RFC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General partial function application&lt;/strong&gt;.  While the prior RFC was declined due to its perceived use cases being insufficient to justify its complexity, there was clear interest in it, and it would vastly improve the usability of function composition.  If a less complex implementation can be found, it would most likely pass and complement this RFC well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A "close but accept object" symbol&lt;/strong&gt;.  Currently, it's not convenient to call a method on an object returned in a pipe step without wrapping it into a closure, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One possible alternative would be a syntax such as $$-&amp;gt;foo(4, 5), which would be logically equivalent to the above.  That would also work for properties, allowing easy reading or writing of "the object in question."  It's likely we could optimize that syntax away the same way FCCs are in this RFC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A ''%%__bind%%'' method or similar on objects&lt;/strong&gt;, possibly with a dedicated operator of its own (such as ''&amp;gt;&amp;gt;='').  If implemented by an object on the left-hand side, the right-hand side would be passed to that method to invoke as it sees fit.  Such a feature would be sufficient to support arbitrary monadic behavior in PHP in a type-friendly way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterable API
&lt;/h2&gt;

&lt;p&gt;There has been on-again-off-again discussion of a new iterable API for some time, one that could replace ''array_map()'', etc. with a more ergonomic, iterator-friendly API.  Pipes are a natural fit for that.&lt;/p&gt;

&lt;p&gt;Consider the case of having reimplemented ''iter\map()'', ''iter\filter()'', ''iter\first()'', ''iter\unique()'', and so on, in C.  Such functions could be written to accept both arrays and iterables, and to return the same type they were given.  Combined with Partial Application, that would lead to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$pdo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Some complex SQL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;someFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;transformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;someCriteria&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are likely other optimizations that a C implementation could make.  All functions would be both pipe-friendly and usable stand-alone.&lt;/p&gt;

&lt;p&gt;An iterable API is not included in this RFC, but this RFC would make implementing one in a fully flexible way substantially easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rejected Features
&lt;/h2&gt;

&lt;p&gt;There was discussion both on-list and off of "auto-partialling" functions after a pipe, such that the operand value is always passed as the first argument of the right side function.  That would allow functions to be written in a "pipe friendly" way by assuming subject-first, and then would not need Partial Application or a wrapping closure in order to provide additional arguments.  This is the way Elixir works, for instance.  For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// This RFC today&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// If PFA passes:&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// With Elixir style&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The use of expressions on the RHS would be supported by wrapping them in parens, to indicate "don't auto-partial.")&lt;/p&gt;

&lt;p&gt;While the author found that compelling, several commenters felt it would be too surprising and unexpected for developers.  For that reason, it has been left out of this RFC.  It would be possible to add support in the future, but only if the auto-partialling became "opt in" with some additional syntax rather than "opt out."  (Like ''$foo |&amp;gt; @array_filter(fn($v) =&amp;gt; $v != 'O')'' or something like that.)&lt;/p&gt;

&lt;h1&gt;
  
  
  Backward Incompatible Changes
&lt;/h1&gt;

&lt;p&gt;None&lt;/p&gt;

&lt;h1&gt;
  
  
  Proposed PHP Version(s)
&lt;/h1&gt;

&lt;p&gt;8.5&lt;/p&gt;

&lt;h1&gt;
  
  
  Open Issues
&lt;/h1&gt;

&lt;p&gt;None&lt;/p&gt;

&lt;h1&gt;
  
  
  Proposed Voting Choices
&lt;/h1&gt;

&lt;p&gt;Yes or no vote.  2/3 required to pass.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Yes&lt;/li&gt;
&lt;li&gt;No
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Patches and Tests
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;PR is available here: &lt;a href="https://github.com/php/php-src/pull/17118" rel="noopener noreferrer"&gt;https://github.com/php/php-src/pull/17118&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;Added in 8.5.&lt;/p&gt;

&lt;p&gt;Final commit: &lt;a href="https://github.com/php/php-src/commit/1c09c0c8323342aaaecbe444b3afa45efbd72ced" rel="noopener noreferrer"&gt;https://github.com/php/php-src/commit/1c09c0c8323342aaaecbe444b3afa45efbd72ced&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;Prior discussion in July 2024: &lt;a href="https://externals.io/message/124149" rel="noopener noreferrer"&gt;https://externals.io/message/124149&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Rejected Features
&lt;/h1&gt;

</description>
      <category>php</category>
      <category>rfc</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Transferring Docker to another disk in Windows</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 07 Nov 2023 11:42:24 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/transferring-docker-to-another-disk-in-windows-545</link>
      <guid>https://dev.to/maksimepikhin/transferring-docker-to-another-disk-in-windows-545</guid>
      <description>&lt;p&gt;Hello everyone Recently, I ran into the problem of insufficient memory on the main disk for a large project that is being deployed in Docker. The issue of transferring Docker resources to a 1TB HDD is fundamentally important, since there were no other options to deploy the project. And that's what came out of it...&lt;/p&gt;

&lt;p&gt;To begin with, I will say that I have a WD Green 120G SSD, where Windows and some important software are installed, and other programs, projects and "personal life" are on the 1TB HDD.&lt;/p&gt;

&lt;p&gt;They sent instructions on how to deploy the project, where there was a fairly large MySQL dump of more than 50 GB in size and a lot of containers. Somehow I didn't pay attention to this question, but in the process of a sooooo long installation, Docker collapsed and said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I won't work, I turn off altogether, I'm stuffy and there's not enough disk space for me to raise your projects here.&lt;br&gt;
I'm tired, I'm leaving!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The news was not pleasant. I turned this Docker this way and that according to all the instructions on the Internet and off the documentation, but it was under Windows that nothing came out. And yes, if you're in daemon.if you change the json data-root, then it simply will not work... It's great, isn't it?!&lt;/p&gt;

&lt;p&gt;After a lot of time of tests and reconfigurations, I was able to find a solution! You may already know about him, so don't judge him harshly. I'm just trying to help "travelers in the Windows world with castrated hard drives."&lt;/p&gt;

&lt;p&gt;And so, stop talking and let's get started. Do everything exactly according to the instructions and you will be happy. I must say right away that I have Windows with Docker on disk C, and I want to move it to disk D, where there is a Programs folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# shutdown wsl
wsl --shutdown
# export data docker-desktop
wsl --export docker-desktop D:\docker-desktop.tar
# remove data's regestration docker-desktop
wsl --unregister docker-desktop
# import data docker-desktop into new directory
wsl --import docker-desktop D:\wslStore\ D:\docker-desktop.tar --version 2
# remove D:\docker-desktop.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these manipulations, all your DockerDesktop stories will be located in D:\wslStore . But, this does not mean that the data (containers, snapshots, etc.) will also be there. To transfer Docker data, an additional bundle of commands is needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# shutdown wsl
wsl --shutdown
# export data docker-desktop-data
wsl --export docker-desktop-data D:\docker-desktop-data.tar
# remove data's regestration docker-desktop-data
wsl --unregister docker-desktop-data
# import data docker-desktop-data into new directory
wsl --import docker-desktop-data D:\Programs\Docker\ D:\docker-desktop-data.tar --version 2
# remove D:\docker-desktop-data.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And only now it is under Windows that your Dokker will store all its junk along the way D:\Programs\Docker\&lt;/p&gt;

&lt;p&gt;Similarly, you can transfer Ubuntu and other stories from wsl/Docker to where you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wsl --export Ubuntu ubuntu.tar
wsl --unregister Ubuntu
wsl --import Ubuntu D:\wslStore\Ubuntu\ ubuntu.tar --version 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I spent a whole day on these solutions: I tried one thing, then another - and here I found a working scheme for changing the Docker data storage directory under Windows.&lt;/p&gt;

&lt;p&gt;I hope this information was helpful. Well, if not, then don't hit too hard :)&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Setting up different PHP versions in Ubuntu on Apache2</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Fri, 18 Feb 2022 14:05:28 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/setting-up-different-php-versions-in-ubuntu-on-apache2-3nm2</link>
      <guid>https://dev.to/maksimepikhin/setting-up-different-php-versions-in-ubuntu-on-apache2-3nm2</guid>
      <description>&lt;p&gt;This is a machine translation of the article "&lt;a href="http://maximepihin.ru/all/nastraivaem-raznye-versii-php-v-ubuntu-na-apache2/" rel="noopener noreferrer"&gt;Configuring different versions of PHP in Ubuntu on Apache2&lt;/a&gt;" from my &lt;a href="http://maximepihin.ru/" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will tell you my experience of setting up PHP of different versions on the same machine running Ubuntu Linux in conjunction with Apache2, xdebug and PHPStorm. It's not new, but I've had problems that PHPStorm didn't catch Debug on different versions, but preferred one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing prerequisites
&lt;/h2&gt;

&lt;p&gt;First you need to completely remove the existing PHP, and then install the required versions (we will install PHP 7.0 and 7.4) from the &lt;strong&gt;ppa:ondrej/php repository&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt purge 'php*'
sudo apt-get install software-properties-common -y
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update -y

# for version 7.0

sudo apt-get install php7.0 php7.0-fpm  libapache2-mod-php7.0 php7.0-mbstring php7.0-pgsql php7.0-xdebug libapache2-mod-fcgid -y

# for version 7.4

sudo apt-get install php7.4 php7.4-fpm  libapache2-mod-php7.4 php7.4-mbstring php7.4-pgsql php7.4-xdebug libapache2-mod-fcgid -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have installed the following packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;php7.X&lt;/strong&gt; is a metapackage used to run PHP applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;php7.X-fpm&lt;/strong&gt; provides a Fast Process Manager interpreter that runs as a daemon and accepts Fast/CGI requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libapahce2-mod-php7.X&lt;/strong&gt; provides a PHP module for the Apache web server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libapache2-mod-fcgid&lt;/strong&gt; contains mod_fcgid, which runs multiple instances of the CGI program to handle concurrent requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;php7.X-mbstring&lt;/strong&gt; module for working with multibyte strings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;php7.X-pgsql&lt;/strong&gt; links PHP to PostgreSQL database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;php7.X-xdebug&lt;/strong&gt; module for debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up xdebug debugging
&lt;/h2&gt;

&lt;p&gt;Now we need to configure &lt;strong&gt;xdebug&lt;/strong&gt; itself in the system and PHPStorm. To do this, go along the path &lt;em&gt;/etc/php/7.X/fpm/&lt;/em&gt; and add the section to &lt;strong&gt;php.ini&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# for version xdebug &amp;lt; 3

[xdebug] 
zend_extension=xdebug.so
xdebug.default_enable=1
xdebug.client_port=9000
xdebug.remote_autostart=1
xdebug.remote_enable=1 
xdebug.remote_host=127.0.0.1 
xdebug.remote_handler="dbgp"
xdebug.remote_port=9000

# for version xdebug &amp;gt;= 3

[xdebug] 
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.start_with_request=yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;PHPStorm&lt;/strong&gt; itself, the settings are made in &lt;em&gt;Settings -&amp;gt; PHP&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the desired version and CLI interpreter&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Debug&lt;/strong&gt; section, uncheck &lt;em&gt;Ignore external connections through unregistered server configurations&lt;/em&gt; and &lt;em&gt;Break at first line in PHP scripts&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Debug port&lt;/strong&gt; to 9000 for xdebug version &amp;lt; 3 and 9003 for xdebug version &amp;gt;= 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may need to add your local site address to the Servers tab, but this may not be necessary. Just in case, I will specify the setting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;Name&lt;/strong&gt; we write any name&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Host&lt;/strong&gt; we write the address without a protocol to your site, for example, mysite.local&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrjtck7mlsnvx9o6kd5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrjtck7mlsnvx9o6kd5b.png" alt="PHPStorm PHP Debug settings" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up virtual hosts in Apache2
&lt;/h2&gt;

&lt;p&gt;You need to create a virtual host configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;     
  ServerName domain.local
  ServerAlias www.domain.local
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/directory

  &amp;lt;Directory /var/www/directory&amp;gt;
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  &amp;lt;/Directory&amp;gt;

  &amp;lt;FilesMatch \.php$&amp;gt;
    # For Apache version 2.4.10 and above, use SetHandler to run PHP as a fastCGI process server
    SetHandler "proxy:unix:/run/php/php7.X-fpm.sock|fcgi://localhost"
  &amp;lt;/FilesMatch&amp;gt;

  ErrorLog ${APACHE_LOG_DIR}/domain-error.log
  CustomLog ${APACHE_LOG_DIR}/domain-access.log combined
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to the line &lt;code&gt;SetHandler "proxy:unix:/run/php/php7.X-fpm.sock|fcgi://localhost"&lt;/code&gt;. You need to replace &lt;strong&gt;X&lt;/strong&gt; with the PHP version. In our case, 0 or 4.&lt;/p&gt;

&lt;p&gt;How to create and activate sites, I think you know. If not, there are plenty of guides on the internet on this subject.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reloading services
&lt;/h2&gt;

&lt;p&gt;At the final stage, you need to overload the services and enable the necessary modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start php7.0-fpm
sudo systemctl start php7.4-fpm
sudo a2enmod actions fcgid alias proxy_fcgi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, now you have 2 versions of PHP on different local sites and xdebug will work on both sites.&lt;/p&gt;

</description>
      <category>php</category>
      <category>ubuntu</category>
      <category>xdebug</category>
      <category>apache</category>
    </item>
    <item>
      <title>Git Organized: My better Git Flow</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 15 Feb 2022 11:58:32 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/git-organized-my-better-git-flow-44pd</link>
      <guid>https://dev.to/maksimepikhin/git-organized-my-better-git-flow-44pd</guid>
      <description>&lt;p&gt;&lt;a href="http://maximepihin.ru/all/git-organized-moy-luchshiy-podhod-k-git-flow/" rel="noopener noreferrer"&gt;In this article&lt;/a&gt;, I review the Git branching approach that I use in all of my development projects. Carefully, this approach is not as effective in maintaining existing software solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the branching organization is built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jbxr0j1gdhwwuyglbha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jbxr0j1gdhwwuyglbha.png" alt="Image description" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing that should be - the main branch responsible for the final product (main / master / stable and others). We upload only ready-made and tested code to this branch, which then goes into release. Using the branch for other purposes is strictly prohibited.&lt;/p&gt;

&lt;p&gt;The second point is the development branch. In this branch, we have a cut of the tested functionality code that is being prepared for release. This branch is not recommended to upload changes that are questionable or have not passed the tests. But, this moment is on the conscience of developers and testers. This development branch must be named as follows: &lt;strong&gt;development_MONTH_YEAR&lt;/strong&gt; - for example, &lt;strong&gt;development_february_2022&lt;/strong&gt;. You can go the easy way and call the dates numbers, but I prefer the verbal form for the months. Why create a branch every month? You will be able to see the development of the product every month and draw your own conclusions. This is convenient because you can tie product releases to the end of the month.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b development_february_2022 main
or
git checkout -b development_february_2022 development_january_2022
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third point is task branches. Some people make new feature branches, but I prefer to create branches for each individual task. Most likely, you are leading a board and an issue in your project. Each issue has its own through number. This is how the branches are named: &lt;strong&gt;task_1&lt;/strong&gt; and so on. Each such branch must necessarily create from the current development branch (current month and year) in order to have actual changes. If changes have been merged into the development branch, then you must pull them into the task branch for updating.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b task_1 development_february_2022
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The merging goes like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge the task branch into the development branch&lt;/li&gt;
&lt;li&gt;Development branch to master&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is simple and clear. And now it is worth mentioning the points on maintaining the board, as this is one of the most important functionalities in project management.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to lead a board
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik37w6l8is59ufyi4cft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik37w6l8is59ufyi4cft.png" alt="Image description" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your whiteboard should have the following columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List&lt;/li&gt;
&lt;li&gt;To do&lt;/li&gt;
&lt;li&gt;Fix&lt;/li&gt;
&lt;li&gt;In progress&lt;/li&gt;
&lt;li&gt;Code review&lt;/li&gt;
&lt;li&gt;Tests&lt;/li&gt;
&lt;li&gt;Awaiting merge&lt;/li&gt;
&lt;li&gt;Done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is such a simple organization of the board. Now I’ll tell you about the life cycle of a task by columns. The tasks that are in the &lt;strong&gt;List&lt;/strong&gt; column are simply a list of all the tasks that have not yet been allocated. In &lt;strong&gt;To do&lt;/strong&gt; - a list of tasks that need to be done in a sprint and already have a distribution for developers. &lt;strong&gt;Fix&lt;/strong&gt; - tasks with errors. In progress - tasks that are being executed at the current time. &lt;strong&gt;Code review&lt;/strong&gt; - tasks that are being checked by the team lead or other people responsible for the final quality of the code. &lt;strong&gt;Tests&lt;/strong&gt; - tasks for testing by testers. &lt;strong&gt;Awaiting merge&lt;/strong&gt; - tasks that are waiting to be merged into the development branch. &lt;strong&gt;Done&lt;/strong&gt; - merged and closed tasks.&lt;/p&gt;

&lt;p&gt;Now a little about the life cycle. First, no more than 3 tasks per developer are selected from the &lt;strong&gt;List&lt;/strong&gt; and placed in &lt;strong&gt;To do&lt;/strong&gt;. When a developer is present to solve no more than 1 task, he moves the task to &lt;strong&gt;In progress&lt;/strong&gt;. After completing the task, you need to transfer it to Code review, from where it goes either to &lt;strong&gt;Fix&lt;/strong&gt; or &lt;strong&gt;Tests&lt;/strong&gt;. If the task got into &lt;strong&gt;Fix&lt;/strong&gt;, then the developer, when he started solving errors, transfers it to &lt;strong&gt;In progress&lt;/strong&gt;, and the cycle repeats. When the task is included in &lt;strong&gt;Tests&lt;/strong&gt;, the cycle is repeated as in Code review. If the tests were successful, then the task is moved to &lt;strong&gt;Awaiting merge&lt;/strong&gt;, and when merged into the development branch, it is moved to &lt;strong&gt;Done&lt;/strong&gt; and closed.&lt;/p&gt;

&lt;p&gt;Agree that this is a fairly simple organization of the task. What do you think?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPD 18/02/2022&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Made an omission on the branch. Look, we are creating a &lt;strong&gt;development&lt;/strong&gt; branch &lt;strong&gt;from the main&lt;/strong&gt; branch, and we are already creating a &lt;strong&gt;monthly development&lt;/strong&gt; branch &lt;strong&gt;from the development&lt;/strong&gt; branch. We fill the &lt;strong&gt;monthly development&lt;/strong&gt; branch &lt;strong&gt;into the development&lt;/strong&gt; branch and then from the development branch we create a new monthly development branch&lt;/p&gt;

</description>
      <category>git</category>
      <category>workflow</category>
      <category>github</category>
    </item>
    <item>
      <title>How do you customize IDE for yourself?</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 04 May 2021 12:59:07 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/how-do-you-customize-ide-for-yourself-5di</link>
      <guid>https://dev.to/maksimepikhin/how-do-you-customize-ide-for-yourself-5di</guid>
      <description>&lt;p&gt;Have you changed the settings of your IDE? If changed, what exactly?&lt;/p&gt;

&lt;p&gt;Personally, I've changed a lot, including window layout, syntax highlighting, error inspection, and other things. Especially for a long time I set up CodeStye for most languages according to the &lt;a href="https://dev.to/maximepihin/psr-experience-php-code-convention-am6"&gt;rules for writing code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I forgot to say that I use PHPStorm for web development.&lt;/p&gt;

</description>
      <category>php</category>
      <category>javascript</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What about PHP components? Ok, let's create. Part 1. Working with headers.</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 04 May 2021 10:30:51 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/what-about-php-components-ok-let-s-create-part-1-working-with-headers-4hgj</link>
      <guid>https://dev.to/maksimepikhin/what-about-php-components-ok-let-s-create-part-1-working-with-headers-4hgj</guid>
      <description>&lt;p&gt;I do a lot of programming in PHP and every time something starts that doesn't reach the end, and so on. As a result of thinking, I realized that every time I decide to write my own system, framework or something else, I run into a problem. The problem is that I do everything around for the system to work, and not the system itself, or I write too dependent code. As a result, I decided that it was worth taking the time to write only components that will not depend on something personalized, but can depend on each other. This approach is also a bit weird, but still passing an interface to work is better than initializing another class inside a class. For example, for some component it will be necessary to use a database, but we do not know exactly what methods are there, so we operate with our own interface, where we ask to implement a class with such and such a method. Something we have gone from the topic to abstraction.&lt;br&gt;
And so, I began to make my written projects in pieces. As a result, nothing efficient came out, as there were strong dependencies. I had to write again ... The first component that I decided to implement was working with headers. Why exactly he? Because most of the work is built around the communication between the server and the client. And here, just, you need to work with headers.&lt;br&gt;
For all my components, I decided to adhere to the same logic of organizing the file structure: a folder for interfaces, a folder for exceptions, and the class file itself. The folder with interfaces must contain at least 1 interface for the class. There may be no exceptions in the folder with exceptions, because you don't always need to have personal exceptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
--- interfaces/
--- --- ClassInterface.php
--- exceptions/
--- --- ClassException.php
--- Class.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's briefly talk about the methods that are available in the class for working with headers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;set(array $params)&lt;/li&gt;
&lt;li&gt;add(array $params)&lt;/li&gt;
&lt;li&gt;remove(string $key)&lt;/li&gt;
&lt;li&gt;removeAll()&lt;/li&gt;
&lt;li&gt;has(string $key)&lt;/li&gt;
&lt;li&gt;get(string $key)&lt;/li&gt;
&lt;li&gt;getAll()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I don’t think it’s necessary to give a clear explanation of the methods, but if you are interested, you can look at the &lt;a href="https://github.com/mepihindeveloper/php-headers" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. True, now I'm translating my work into English, so don't be too surprised.&lt;/p&gt;

&lt;p&gt;And at the end of the part, I want to note that there will be even more classes in the future. I try not to clutter up the post with code, since you can all look at &lt;a href="https://github.com/mepihindeveloper/php-headers" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. You can also download the project from &lt;a href="https://packagist.org/packages/mepihindeveloper/php-headers" rel="noopener noreferrer"&gt;composer packagist&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create your own composer project</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Thu, 17 Dec 2020 08:26:19 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/create-your-own-composer-project-2aih</link>
      <guid>https://dev.to/maksimepikhin/create-your-own-composer-project-2aih</guid>
      <description>&lt;p&gt;Hey. It has always been interesting to create your own project in composer, as it is a more modular and adequate approach when developing large applications. What is it for? The answer is simple: this is necessary in order to cut your tools into modules that can be used separately. For example, you can create a module to work with sessions, files, and more. Suppose you are making your own framework, which has a lot of self-written modules. And I, as a third party developer, want to use only 1 or 2. I don't need the whole framework! What to do? By resorting to packages (modules), you can provide this flexibility in the toolbox.&lt;/p&gt;

&lt;p&gt;To implement simple packages, the composer config file looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "kernel",
    "description": "",
    "license": "",
    "keywords": [
        "",
    ],
    "authors": [
        {
            "name": "",
            "email": ""
        }
    ],
    "require": {
        "php": "^7.4|^8.0"
    },
    "autoload": {
        "psr-4": {
            "kernel\\": "kernel"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you want to make a project like Laravel, Yii 2 and other frameworks, then you need to have both the project core and its skeleton. In the case of the kernel, everything is quite transparent - the root folder of all the internals of the framework, where we will not climb. And the skeleton is the wrapper, the structure of the entire project. For example, a skeleton can contain empty folders required by the kernel, root files, and so on.&lt;/p&gt;

&lt;p&gt;If you want to work with the kernel and skeleton, then the config file will look like this:&lt;br&gt;
&lt;strong&gt;Kenrel&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "kernel",
    "description": "",
    "license": "",
    "keywords": [
        "",
    ],
    "authors": [
        {
            "name": "",
            "email": ""
        }
    ],
    "require": {
        "php": "^7.4|^8.0"
    },
    "autoload": {
        "psr-4": {
            "kernel\\": "kernel"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Skeleton&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "username/kernel-skeleton",
    "type": "project",
    "description": "",
    "license": "",
    "keywords": [
        "",
    ],
    "authors": [
        {
            "name": "",
            "email": ""
        }
    ],
    "require": {
        "php": "^7.4|^8.0",
        "username/kernel": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "kernel\\": "kernel"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there is some information hidden here, but the whole point is that the kernel is of type type by default and is a library. And the project skeleton has a &lt;strong&gt;type project&lt;/strong&gt;. The kernel and its version were specified in the dependencies.&lt;/p&gt;

&lt;p&gt;The launch of the whole miracle was like this: &lt;code&gt;composer create-project HERE_SKELETON PROJECT_NAME&lt;/code&gt;. &lt;code&gt;create-project&lt;/code&gt; will both pull and install all dependencies at once.&lt;/p&gt;

&lt;p&gt;Thus, it turns out that to implement the libraries, you need to have only one project on Github, and if you want to use the project format, then you need to create a separate repository for the project skeleton and its core.&lt;/p&gt;

</description>
      <category>composer</category>
      <category>programming</category>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>PSR + Experience = PHP code convention</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 15 Dec 2020 22:14:04 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/psr-experience-php-code-convention-am6</link>
      <guid>https://dev.to/maksimepikhin/psr-experience-php-code-convention-am6</guid>
      <description>&lt;p&gt;The following points were formed by analyzing the existing approaches of companies and personal experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  File and folder naming rules
&lt;/h1&gt;

&lt;p&gt;All names for folders and files should be meaningful and self-explanatory (not requiring additional clarification).&lt;/p&gt;

&lt;h2&gt;
  
  
  Folders
&lt;/h2&gt;

&lt;p&gt;All folders are named in lowercase, word-delimited using the &lt;code&gt;-&lt;/code&gt; (minus) character.&lt;/p&gt;

&lt;p&gt;If the folder contains classes that belong to the namespace, then the folder is named according to the name of the namespace.&lt;/p&gt;

&lt;p&gt;Allowed characters for naming folders: Latin letters and the &lt;code&gt;-&lt;/code&gt; (minus) symbol.&lt;/p&gt;

&lt;h2&gt;
  
  
  Files
&lt;/h2&gt;

&lt;p&gt;All files related to the project are named in lowercase word-delimited using the &lt;code&gt;-&lt;/code&gt; (minus) character.&lt;/p&gt;

&lt;p&gt;If the file is a class file, it is named according to the class name.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rules for naming namespaces, classes, methods and variables
&lt;/h1&gt;

&lt;p&gt;All names should be meaningful and self-explanatory (not requiring additional clarification).&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;Namespace names must be in lowercase and consist of one word. If it is necessary to name namespaces for more than one word, it is split into constituent parts, which are nested namespaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classes
&lt;/h2&gt;

&lt;p&gt;Class names must match &lt;code&gt;PascalCase&lt;/code&gt;. In &lt;code&gt;PascalCase&lt;/code&gt;, each word starts with a capital letter.&lt;/p&gt;

&lt;p&gt;Traits are postfixed with &lt;code&gt;Trait&lt;/code&gt;. Interfaces are postfixed with &lt;code&gt;Interface&lt;/code&gt;. Abstract classes are prefixed with &lt;code&gt;Abstract&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;Method names must match &lt;code&gt;camelCase&lt;/code&gt;. &lt;code&gt;camelCase&lt;/code&gt; must start with a lowercase letter, and the first letter of each subsequent word must be capitalized. All words are written together&lt;/p&gt;

&lt;p&gt;The following rules apply to method names:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The name of the method should convey the intentions of the programmer&lt;/li&gt;
&lt;li&gt;The name of the method should tell why this method exists, that it
does and how it is used (&lt;code&gt;isPostRequest&lt;/code&gt;, &lt;code&gt;getRequestType&lt;/code&gt;, &lt;code&gt;parseSchemaElement&lt;/code&gt;, &lt;code&gt;renderPageWithSetupsAndTeardowns&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The name of the method should not be short&lt;/li&gt;
&lt;li&gt;The name of the method must begin with a verb&lt;/li&gt;
&lt;li&gt;Names of &lt;code&gt;boolean&lt;/code&gt; methods must contain the verb &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;has&lt;/code&gt; or &lt;code&gt;can&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Variables
&lt;/h2&gt;

&lt;p&gt;Variable names must match &lt;code&gt;camelCase&lt;/code&gt;. &lt;code&gt;camelCase&lt;/code&gt; must start with a lowercase letter, and the first letter of each subsequent word must be capitalized. All words are written together&lt;/p&gt;

&lt;p&gt;Constants must match &lt;code&gt;UPPER_CASE_SNAKE_CASE&lt;/code&gt;. In &lt;code&gt;UPPER_CASE_SNAKE_CASE&lt;/code&gt;, all words are written in capital letters, and spaces are replaced with underscores.&lt;/p&gt;

&lt;p&gt;The following rules apply to variable names:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The name of the variable should convey the intentions of the programmer&lt;/li&gt;
&lt;li&gt;The name of the variable should tell you why this variable exists, what it does and how it is used&lt;/li&gt;
&lt;li&gt;The name of the variable should not be short&lt;/li&gt;
&lt;li&gt;The name of the variable must not use the data type. The exception is &lt;code&gt;Map&lt;/code&gt; (&lt;code&gt;$typesMap&lt;/code&gt;, &lt;code&gt;$statesMap&lt;/code&gt;), because otherwise, it cannot be distinguished from an array with data.&lt;/li&gt;
&lt;li&gt;If a variable stores a trait, then it must be included in the name (&lt;code&gt;unpaidProject&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Variables reflecting the properties of the object must include the name of the object (&lt;code&gt;userIsAdmin&lt;/code&gt;, &lt;code&gt;messageIsSend&lt;/code&gt;, &lt;code&gt;figureCanBePainted&lt;/code&gt;, &lt;code&gt;projectName&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Variables and properties of an object must be nouns and named so that they are read correctly when used, and not when initialized&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Poorly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;expire_at&lt;/span&gt;
&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setExpireAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getExpireAt&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;expiration_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setExpirationDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getExpirationDate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Names of &lt;code&gt;boolean&lt;/code&gt; variables must contain the verb &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;has&lt;/code&gt; or &lt;code&gt;can&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Negative logical names are prohibited&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Poorly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isInvalid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isNotValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$accessManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isAccessDenied&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$accessManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isAccessAllowed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$accessManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;If there are properties (clause 8 and similar), the order of the variable name consists of: the name of the object in relation to which the variable is used), the property and the continuation of the variable name (&lt;code&gt;userHasRoleAdmin&lt;/code&gt;, &lt;code&gt;statusIsActive&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Code design rules
&lt;/h1&gt;

&lt;p&gt;First of all, the namespace is put, which is used (if any). Next, the constructs of using classes (&lt;code&gt;use&lt;/code&gt;) are written. In case of using several&lt;br&gt;
Classes of the same namespace are grouped using the &lt;code&gt;{...}&lt;/code&gt; construction. Next comes the class declaration.&lt;/p&gt;

&lt;p&gt;Curly braces appear on the same line and are separated by a space.&lt;/p&gt;

&lt;p&gt;Round brackets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside are not separated by a space.&lt;/li&gt;
&lt;li&gt;Outside separated by spaces &lt;strong&gt;&lt;a href="https://www.php.net/manual/ru/language.control-structures.php" rel="noopener noreferrer"&gt;control structures&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;There is no space after the method / function name.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each variable must be declared on a new line.&lt;/p&gt;

&lt;p&gt;Conditions and service calls of methods are separated by line breaks, variables and work with them by line breaks are not separated.&lt;/p&gt;

&lt;p&gt;There is no additional line break inside conditions and loops.&lt;/p&gt;

&lt;p&gt;The content of the class is delimited at the top by one blank line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InterfaceType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myProp'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The return value (&lt;code&gt;return&lt;/code&gt;) must be preceded by a line break if the method does not consist of a single line.&lt;/p&gt;

&lt;p&gt;If the condition is large, then be sure to select it in one or more semantic expressions and use it (them) in the condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Poorly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;IS_REGISTRATOR&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'W'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'D'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remark&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subres_level&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user_info&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;selected_title&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;boss&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$user_info&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;selected_title&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$doc_signer_tid&lt;/span&gt; &lt;span class="o"&gt;||!&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usertid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subres_level&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$user_info&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;selected_title&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usertid&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$docIsInWorkAcceptOrDraft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$bossHasSignerPriviledge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$userCanSign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$docIsInWorkAcceptOrDraft&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$bossHasSignerPriviledge&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$userCanSign&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code commenting
&lt;/h2&gt;

&lt;p&gt;In general, comments are prohibited (&lt;strong&gt;NOT&lt;/strong&gt; "always"). Any piece of code that needs to be highlighted or commented out should be placed in a separate method.&lt;/p&gt;

&lt;p&gt;Comments should be placed before the declaration of classes, variables and methods and should be formatted in accordance with PHPDoc. The comment before the class should describe the business logic and reflect its purpose with examples of use.&lt;/p&gt;

&lt;p&gt;Single-line comments are denoted by &lt;code&gt;//&lt;/code&gt;, and multi-line &lt;code&gt;/*...*/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finished algorithms taken from an external source must be marked with a link to the source.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rules for writing code
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Where it makes sense,&lt;/strong&gt; &lt;code&gt;declare (strict_types = 1);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Functions / methods use &lt;code&gt;null&lt;/code&gt; instead of missing scalar value. &lt;code&gt;0&lt;/code&gt; and an empty string cannot be used as an indicator of a missing value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// message was not sent&lt;/span&gt;
&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2017-01-01'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// an empty message was sent&lt;/span&gt;
&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2017-01-01'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You cannot change the variables that are passed to the method as input (exception - if this variable is an object).&lt;/p&gt;

&lt;p&gt;You cannot assign the same value to several variables. To check if a key exists in an associative array, use &lt;code&gt;array_key_exists&lt;/code&gt;, not &lt;code&gt;isset&lt;/code&gt;. You cannot mix string and numeric keys in an array. Associative arrays cannot be sorted.&lt;/p&gt;

&lt;p&gt;Lines are surrounded by single quotes. Double quotes are only used if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There must be single quotes inside the string&lt;/li&gt;
&lt;li&gt;Variable substitution is used inside the string&lt;/li&gt;
&lt;li&gt;Specials are used inside the line. characters &lt;code&gt;\n&lt;/code&gt;, &lt;code&gt;\r&lt;/code&gt;, &lt;code&gt;\t&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instead of unnecessary concatenation, we use variable substitution in double quotes&lt;/p&gt;

&lt;p&gt;Methods should use as much typing as possible, including the return type (&lt;code&gt;: type&lt;/code&gt;). All parameters and their types must be described in the method declaration or in &lt;strong&gt;PHPDoc&lt;/strong&gt;. Name methods that start with &lt;code&gt;check&lt;/code&gt; and &lt;code&gt;validate&lt;/code&gt; should throw exceptions and not return values.&lt;/p&gt;

&lt;p&gt;All class methods should be &lt;code&gt;private&lt;/code&gt; by default. If the method is used by the heirs of the class, then it is declared &lt;code&gt;protected&lt;/code&gt;. If used by third party classes then &lt;code&gt;public&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the method can return &lt;code&gt;null&lt;/code&gt;, then it is desirable to implement the &lt;strong&gt;Null object&lt;/strong&gt; design pattern, or throw an exception, or return a special case object (example: an empty array).&lt;/p&gt;

&lt;p&gt;When returning from a data method of the &lt;code&gt;json&lt;/code&gt; type - it is unacceptable to write&lt;code&gt;return true&lt;/code&gt;, always use the construction &lt;code&gt;return ['success' =&amp;gt; ['message' =&amp;gt; '.....']]&lt;/code&gt; or &lt;code&gt;['error' =&amp;gt; ['message' =&amp;gt; '.....']]&lt;/code&gt; . &lt;code&gt;message&lt;/code&gt; is given as an example, you can use any keys in an unlimited number.&lt;/p&gt;

&lt;p&gt;The method must clearly distinguish between normal and exceptional situations.&lt;/p&gt;

&lt;p&gt;By default, exception texts should not be shown to the user. They are meant for logging and debugging. The exception text can be shown to the user if it is explicitly intended to do so.&lt;/p&gt;

&lt;p&gt;In a conditional statement, only the &lt;code&gt;boolean&lt;/code&gt; value must be checked. When comparing non-&lt;code&gt;boolean&lt;/code&gt; variables, strict comparison with type casting (&lt;code&gt;===&lt;/code&gt;) is used, automatic casting and loose comparison are not used.&lt;/p&gt;

&lt;p&gt;Poorly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;// $user is of type object&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the AND and OR operators in a conditional expression at the same time, be sure to prioritize parentheses.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>convention</category>
    </item>
    <item>
      <title>Opinion on PSR-1: Basic Coding Standard</title>
      <dc:creator>Maksim Epikhin</dc:creator>
      <pubDate>Tue, 15 Dec 2020 18:31:04 +0000</pubDate>
      <link>https://dev.to/maksimepikhin/opinion-on-psr-1-basic-coding-standard-28mf</link>
      <guid>https://dev.to/maksimepikhin/opinion-on-psr-1-basic-coding-standard-28mf</guid>
      <description>&lt;p&gt;After reading PSR-1, some thoughts came up that I would like to share with the programming community in order to get stories about your experience.&lt;/p&gt;

&lt;p&gt;PSR-1: Basic Coding Standard — A standard that recommends rules for formatting and coding. Styling is how to write code, and writing is what to write.&lt;/p&gt;

&lt;p&gt;The subtext PSR-1 says that you should not use mixing of code and logical conclusions of the code. I put it a little not clearly, but then you will understand that PSR-1 does not recommend writing a class, displaying it on the screen and initializing properties in one file.&lt;/p&gt;

&lt;p&gt;All PHP files must use either &lt;code&gt;&amp;lt;?php&lt;/code&gt; or &lt;code&gt;&amp;lt;?=&lt;/code&gt;. Everything is obvious and understandable here, the first tag says about the declaration of a php code section, and the second is a short echo record, that is, output.&lt;/p&gt;

&lt;p&gt;The files should also be in UTF-8 encoding without BOM, which makes sense. There was once a case in a project where there were several programmers. So, there one somehow managed to insert a BOM symbol and because of this, parsing files broke.&lt;/p&gt;

&lt;p&gt;It also says that it is not recommended to use multiple side effects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugpobimz6z9km6gjlebg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugpobimz6z9km6gjlebg.png" alt="Code" width="476" height="392"&gt;&lt;/a&gt;&lt;br&gt;
Well, here the moment is extremely controversial. Although the standard recommends using an autoloader according to its PSR-0 and PSR-4 standards. On the one hand, yes, but there may be application initialization at a single entry point. In short, the moment is doubtful. In the same Yii2 this approach is not followed … I would not pay attention to this very recommendation.&lt;/p&gt;

&lt;p&gt;Let’s go to the section of class names and namespaces (namespace). Here I agree that the class file should contain only this class, that the class should be in the namespace. Class naming should be in &lt;code&gt;StudlyCaps&lt;/code&gt; format. We will not consider options for writing code for PHP versions &amp;lt;7.0, as there are some nuances, and the demand for versions below is quite small.&lt;/p&gt;

&lt;p&gt;We name constants in uppercase, separating words with underscores &lt;code&gt;DATE_APPROVED&lt;/code&gt;. Everything is logical and understandable here, there is no point in naming them like properties or variables. It is necessary to clearly distinguish constants from properties.&lt;br&gt;
But with the naming of properties, I do not agree with the recommendations. PSR-1 recommends using one of the following formats: &lt;code&gt;$StudlyCaps&lt;/code&gt;, &lt;code&gt;$camelCase&lt;/code&gt;, or &lt;code&gt;$under_score&lt;/code&gt;. I don’t really like the messy code and rely on the opinion of each programmer. Personally, I, probably like many programmers, believe that there is only one style to use, and it should be &lt;code&gt;$camelCase&lt;/code&gt;. Moreover, the standard is tricky, it says that these rules can come from code suppliers of different levels … Now, if the naming standard was adopted specifically, there would be no disagreements. Although I have not seen writing code in a different format from &lt;code&gt;camelCase&lt;/code&gt; for a long time.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;camelCase()&lt;/code&gt; method naming, I completely agree and support. It is logical that we name classes with a capital letter, constants with a small letter, methods with a small letter. And, in principle, you can distinguish one from the other simply by writing.&lt;/p&gt;

&lt;p&gt;Thank you for your attention, I hope that the material was useful, although it is a statement of thoughts on reading PSR-1.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
