PHP wish-list

A random list of missing language features in PHP. I do mostly Kotlin nowadays, so this is quite inspired by that language. I think these features could be (somehow) “easily” added into PHP.

No new keyword

It removes unnecessary keywords and allows to easily chain method calls.

class Url
{
    function something(): static { return $this; }
}

$author1 = Url();

$author2 = Url()->something();
// instead of 
// $author2 = (new Url())->something();

This cool feature also allows a nice trick – using a function named as the interface to create different implementations depending on the arguments:

interface Driver {}
class MysqlDriver implements Driver {}
class PgsqliDriver implements Driver {}

function Driver(string $dsn): Driver
{
    if (strpos($dsn, "mysqli") !== false) {
        return MysqliDriver($dsn);
    } elseif (strpos($dsn, "pgsql") !== false) {
        return PgsqliDriver($dsn);
    } /* ... */
}

Conflicts would be simply resolved as the function is always preferred if a class and function with the same name are present in the scope. Be aware the same named interface wouldn’t cause any trouble. Also, the new keyword would still work and wouldn’t be deprecated.

Extension functions

This is a must for better code design. The class will provide only the minimal API and users can easily and cleanly extend the class. The extension has access only to the public API -> i.e. it is just a syntax sugar.

namespace MyNamespace;

function Connection.inTransaction(callable $cb)
{
    $this->beginTransaction();
    try {
        $result = $cb();
        $this->commitTransaction();
        return $result;
    } catch (Exception $e) {
        $this->rollbackTransaction();
        throw $e;
    }
}

These extension functions would have to be always imported to be “callable”. Defining the same extension function would cause a standard error.

The open question is the import syntax. Would be PHP able to resolve the proper function if there were more functions with the same name extending different classes? This resolution issue is similar to overloading, which is not currently present in PHP.

use function MyNamespace\inTransaction;
// alternatively
use function MyNamespace\Connection.inTransaction;

$connection->inTransaction(/* ... */);

Overloading

Since PHP has types in function definitions, it would be great to have overloading. That would greatly help codebase progression and allow changes without BC breaks. Also, the static analysis would be able to detect which call is deprecated and which is not (in contradiction to taking both types and logging deprecated warning in runtime).

/**
 * @deprecated Use getValue with property object.
 */
function getValue(string $key) {}

function getValue(Property $property) {}

Immutability helpers (data class & read-only)

Immutable classes are quite powerful but it’s quite difficult to design them in current PHP. Mostly because we need “modifying” methods to allow change of any property (i.e. these methods would be able to reflect property additions/removals). With named args in PHP 8.0, it is possible to write them by hand, but some auto-generated method would be quite nice. A data class modifier would do this for me. Also, the read-only modifier is needed to make the class immutable.

data class User
{
    public __construct(
        public readonly string $name,
        public readonly int $age,
    ) {}
}

$user = User(name: "John", age: 3)->copy(name: "Anie");
// === User(name: "Anie", age: 3)

Anything else?

Of course, I would gladly see generics and other stuff. But these are quite difficult topics to get right and correctly incorporated into lang. So just these would be nice.