Sometimes multiple behaviors are necessary for a routine to be able to do its job but there is no common interface for those behaviors. Sometimes a common interface can be extracted, but this is not doable in third-party code. This RFC proposes a way to define types that must satisfy multiple types.
Intersection types allow the programmer to write multiple type declarations for a parameter or return value. The value must satisfy all of the declared types. Each type is separated by ampersand (&
).
Here is a practical example. Given this definition:
function RecordsToList(Countable & Traversable $input): String { if (count($input) > 0) { $output = "<ol>\n"; foreach ($input as $value) { $output .= "\t<li>" . htmlentities($value) . "</li>\n"; } $output .= "</ol>\n"; return $output; } else { return "<p>No items to display.</p>\n"; } }
This will error (see on 3v4l.org):
// Argument 1 passed to RecordsToList() must be Countable and Traversable, array given echo RecordsToList(["Lennon", "McCartney", "Starr", "Harrison"]);
This works correctly (see on 3v4l):
echo RecordsToList(new ArrayObject(["Lennon", "McCartney", "Starr", "Harrison"])); // Output: // <ol> // <li>Lennon</li> // <li>McCartney</li> // <li>Starr</li> // <li>Harrison</li> // </ol>
Note that if Union Types are also accepted then something like this will be possible1), allowing for an array or an object that satisfies both Countable and Traversable:
function RecordsToList(Array | (Countable & Traversable) $input): String { if (count($input) > 0) { $output = "<ol>\n"; foreach ($input as $value) { $output .= "\t<li>" . htmlentities($value) . "</li>\n"; } $output .= "</ol>\n"; return $output; } else { return "<p>No items to display.</p>\n"; } }
When union and intersection types are in the same expression they must be grouped with parenthesis (demonstrated above). The following is invalid:
function RecordsToList(Array | Countable & Traversable $input): String { // ... }
There are no known backwards compatibility breaks.
This feature is proposed for PHP 7.1.
Make sure there are no open issues when the vote starts!
This feature will have a simple Yes/No vote requiring two-thirds in the affirmative.
A proof of concept patch has been provided by Joe Watkins and Bob Weinand: https://github.com/php/php-src/pull/1887
Note there are multiple features contained in this patch, such as union types.