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