PHP Annotated — May 2021


PHP 8.0 is gaining momentum and adoption is increasing, as evidenced by Composer’s statistics.

Meanwhile, PHP internals have accepted a bunch of changes for PHP 8.1, including a new never type and namespaces in bundled PHP extensions, and some features that will be deprecated.

The PHP 8.1 release managers have been selected, and there are several interesting proposals under discussion, including property accessors, pure intersection types, and final constants.

Read more about this news in the May edition of PHP Annotated. As usual, we’ve carefully selected a collection of articles, tools, videos, and streams for you.

  • [RFC] never type

    PHP 8.1 will have a new type for returned values: never.

    A function or method declared with the never type indicates that it will never return a value, and it either throws an exception or terminates with a call of type die(), exit(), trigger_error().

    It is an empty bottom type and is a subtype of all other types, and there are similar types in Python, Rust, Kotlin, and TypeScript. This type improves static analysis.

    function redirect(string $uri): noreturn {
        header('Location: ' . $uri);
        exit();
    }
    
    function redirectToLoginPage(): noreturn {
        redirect('/login');
    }

    You can find more details on PHP.Watch or listen to the PHP Internals News podcast with Matt Brown and Ondřej Mirtes.

  • [RFC] Deprecate implicit non-integer-compatible float to int conversions

    In PHP 8.1, an E_DEPRECATED notice will be thrown when float is converted into int and fractional part is lost. Later, in PHP 9.0, this will cause a TypeError.

    function acceptInt(int $i) {
            var_dump($i);
    }
    acceptInt(3.1415);
    
    > int(3) // Deprecation notice

    Learn more from the 🔈 PHP Internals News podcast #83 with George Peter Banyard.

  • [RFC] Phasing out Serializable

    In PHP 8.1 the Serializable interface will be deprecated. A deprecation notice will be thrown when the class uses only this interface, that is, if the class does not additionally have the new magic methods __serialize() and __unserialize().

  • [RFC] Namespaces in bundled PHP extensions

    This marks a small step towards cleaner PHP! New symbols (classes, interfaces, etc.) in extensions will now have to use namespaces.

    Here’s an example. The resource type is de-facto obsolete in PHP, and all existing resources are slowly being migrated to objects. In PHP 8.1 some resources will be replaced with the following namespaced classes:

    IMAPConnection -> IMAPConnection
    FTPConnection -> FTPConnection
    LDAP -> LDAPConnection
    LDAPResult -> LDAPResult
    LDAPResultEntry -> LDAPResultEntry
    PgSql -> PgSqlConnection
    PgSqlResult -> PgSqlResult
    PgSqlLob -> PgSqlLob
  • [RFC] Add return type declarations for internal methods

    Most of the built-in methods in PHP 8.0 have received parameters and return type declarations. In some cases, however, this could not be done, like for the return values of public non-final methods. The problem is that they can be overridden in user code.

    Here is an example to illustrate the problem
    class SomeStandardClass
    {
        public function method(): int {}
    }
    
    class UserClass extends SomeStandardClass
    {
        public function method() {}
    }
    
    // Fatal error: Declaration of UserClass::method() must be compatible with SomeStandardClass::method()
    

    There will now be a gradual migration for such cases. In PHP 8.1, all internal methods will also get the missing types. If they are overridden in user code, a Deprecation notice will be thrown.

    class MyDateTime extends DateTime
    {
        public function modify(string $modifier) { return false; }
    }
    
    // Deprecated: Declaration of MyDateTime::modify(string $modifier) should be compatible with DateTime::modify(string $modifier): DateTime|false
    
  • Release managers for PHP 8.1 have been selected

    There will be three managers this time around: the experienced Joe Watkins (pthreads, parallel, pcov), and two newcomers, Patrick Allaert (blackfire.io) and Ben Ramsey (ramsey/uuid). Check PHP Internals News podcast #84 with Ben and Patrick.


    New proposals for PHP 8.1:

  • [RFC] Partial Function Application

    Partial function application (partial functions) is when only some arguments are bound on function call, and the others remain as parameters to be passed later.

    For example, here is a full function:

    function whole($one, $two) {
        /* ... */
    }

    And here’s a partial one based on it:

    $partial = whole(?, 2);

    In this case, the partial signature will look like this:

    function($one) {
        /* ... */
    }

    Why is this needed?

    Firstly, you can now get a reference to any function or method and pass it wherever Callable is expected. For example, you could do this

    array_map(Something::toString(?), [1, 2, 3]);
    array_map(strval(?), [1, 2, 3]);
    
    // instead of
    array_map([Something::class, 'toString'], [1, 2, 3])
    array_map('strval', [1, 2, 3]);

    And secondly, as a consequence, it will be possible to implement the pipe operator |>:

    $result = "Hello World"
        |> htmlentities(?)
        |> explode(?);

    See it in action at 3v4l.org.

    Thanks to Larry Garfield, Joe Watkins, Levi Morrison, and Paul Crovella for the RFC and the implementation.

  • [RFC] Property Accessors

    Nikita has finalized the implementation of the property accessors, and the proposal is now officially under discussion.

    The bottom line is that traditional getters and setters are not convenient to use, and the magic methods __get and __set are not specific. The new accessors are meant to fix these issues.

    The syntax is inspired by C#:

    class Foo {
        public $prop {
            get { /* ... */ }
            set { /* ... */ }
        }
    }
    

    You can use them to implement read-only properties:

    class User {
        public string $name { get; }
    
        public function __construct(string $name) {
            $this->name = $name;
        }
    }
    

    And you can specify asymmetric access, i.e. make them public or private separately for reading and writing:

    class User {
        public string $name { get; private set; }
    
        ...
    }
    

    Or you can use them as full-fledged methods for validation or other actions:

    class Foo {
        public int $bar {
            get {
                error_log('Getting $bar');
                return $this->bar;
            }
            set {
                assert($bar > 42);
                $this->bar = $bar;
            }
        }
    }
    
  • [RFC] Pure intersection types

    Union types were added in PHP 8.0, and this RFC proposes to add intersection types.

    The syntax is TypeA&TypeB, and it means that the variable must be both instanceof TypeA and instanceof TypeB.

    Details
    class A {
        private Traversable&Countable $countableIterator;
    
        public function setIterator(Traversable&Countable $countableIterator): void {
            $this->countableIterator = $countableIterator;
        }
    
        public function getIterator(): Traversable&Countable {
            return $this->countableIterator;
        }
    }
    

    The proposal is called “pure intersection types” because combinations with union types are not supported and are being left for future consideration. Aliases for complex types are also being left for the future.

  • [RFC] Deprecate ticks

    There is a tick mechanism in PHP: declare(ticks=1). It was originally needed to track pcntl signals. Now you can use pcntl_signal() and pcntl_async_signals() for this, which is why there’s been a suggestion to deprecate ticks in PHP 8.1 and remove them completely in PHP 9.

  • [RFC] Final class constants

    The author of this RFC proposes a final modifier for constants, so that they cannot be overridden in child classes.

    Details
    class Foo
    {
        final public const X = "foo";
    }
    
    class Bar extends Foo
    {
        public const X = "bar";
    }
    
    // Fatal error: Bar::X cannot override final constant Foo::X
    

    Fun fact from RFC: constants in interfaces are already final.

  • A couple more links for those who would like to start contributing to PHP source:
  • If you have any interesting or useful links to share via PHP Annotated, please leave a comment on this post or send me a tweet.

    Source link

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top