Okay,

No one seemed extremely interested in my notes about static
type-references<http://marc.info/?t=136327849600002&r=1&w=2>- I want
to bring up something closely related that could possibly be even
more useful, in particular for things like form-helpers, which remains as
one of the things that just can't be done in PHP as elegantly as it can in
some other languages.

I'm not sure if de-referencing is the correct term? I'm talking about the
ability to use a property-reference indirectly - meaning, don't read the
property, don't write the property, but reference the property in a way
that permits you to read/write the property later on.

In this example, I'm using ^ as the de-reference operator:

class User
{
    public $email;
}

$user = new User();

$form = new FormHelper($user);

echo $form->textInput(^$user->email);

Note the ^ operator in the last line - we're not passing the value of
$user->email to FormHelper::textInput() but a reference to it... assuming a
new internal PropertyReference class, it's declaration might look like this:

class FormHelper
{
    public function textInput(PropertyReference $prop)
    {
        $name = $prop->className . '[' . $prop->propertyName . ']';
        $value = $prop->getValue();

        return "<input type='text' name='{$name}' value='{$value}' />";
    }

    ....
}


The new PropertyReference class might have an interface like the following:

class PropertyReference
{
    public readonly object $object; // the object that was referenced
    public readonly string $className; // the type of object that was
referenced
    public readonly string $propertyName; // the name of the property that
was referenced

    public function getValue(); // read and return the property-value
    public function setValue($value); // write the property-value
}


For a statement like this:

$prop = ^$user->email;

The ^ operator does something equivalent to:

$prop = new PropertyReference();

$prop->object = $user;
$prop->className = get_class($user);
$prop->propertyName = 'email';

$prop->getValue = function () use ($user) {
    return $user->email;
};

$prop->setValue = function ($value) use ($user) {
    $user->email = $value;
};


So essentially, you get all the information about the object and property,
and a way to read/write that property, with one character - something that
would enable hugely convenient APIs for things like form-helpers,
data-mappers and object/relational-mappers.

When the object-type is known in IDEs (as it is in properly documented
code) this also addresses the same issue as static type-references,
allowing for static analysis and automated refactoring, but with a much
shorter and more convenient syntax - not needing to explicitly reference
the class-name, and with the added benefit of knowing the instance, both of
which are hugely important for form-helpers and mappers.

Note that the getValue() and setValue() closures resolve properties the
usual way - that is, you can de-reference magic properties too, since no
attempt is made to read or write the property until getValue() or
setValue() is made.

Most use-cases for referencing class and property-names are situations like
these, so this kind of kills two birds with one stone - a static way to
reference properties, but with the addition of providing the actual
object-context. And the shortest possible syntax.

What do you think?

- Rasmus Schultz

Reply via email to