Okay,
No one seemed extremely interested in my notes about static
type-referenceshttp://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
Okay,
No one seemed extremely interested in my notes about static
type-referenceshttp://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 referencedpublic 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
Maybe I didn't understand what you mean, but if you want property
references, why not just use, well, property references?
function foo(&$ref) { $ref = 'a'; }
$a = new Obj;
foo($a->prop);
var_dump($a->prop) // string(1) "a"
Also works for magic properties, assuming your correctly declared them
using &__get.
If you want more than just get/set, but also info on the property, why not
pass a ReflectionProperty or a modification thereof which has a pre-bound
object? Why do you need a new operator for this?
Nikita
Maybe I didn't understand what you mean, but if you want property
references, why not just use, well, property references?
Property-references don't know what property they're referencing - they
reference the object/value held by the property, not the property itself.
If you want more than just get/set, but also info on the property, why not
pass a ReflectionProperty or a modification thereof which has a pre-bound
object? Why do you need a new operator for this
That's what we have to do currently - that's why form-helpers and ORMs
currently rely on strings for property-references...
echo $form->textInput($user, 'email');
This example is fairly straight forward, and PHP developers are probably
used to reading code like this by now - but the meaning becomes
increasingly obscured the further you take things out of context:
$form = new FormHelper($user);
echo $form->textInput('email');
Now you have to think a little more to understand what's going on - the API
is more convenient now, but more obscured. It's also less flexible, since
now you have to manually switch objects or create more form-helpers to
handle more than one object.
echo $form->textInput($property_name);
Even more obscured, since now your local variable is definitely a string,
and you can no longer see which property we're talking about.
The root of this problem is the fact that 'email' is a string - the fact
that it references a source-code element is something that is merely
implied but can't be proven, which means you can't have proper IDE support
or static analysis. (by other means than sheer guesswork.)
As opposed to:
echo $form->textInput(^$user->email);
There is no question that you're referring to an object property here -
it's not a string and it's also an atomic reference to a particular object
and property combined, as opposed to the string and object as a detached
reference and value pair. Even if you have to pass these around:
class FormHelper
{
public function textInput(PropertyReference $prop)
{
return $this->renderInput('text', $prop);
}
protected function renderInput($type, PropertyReference $prop)
{
....
}
}
You're no longer passing around a string detached from it's object context,
having to keep the object-reference as state or pass it around as a
separate argument from the property-name - the idea is to have formal
language-level support for a reference to an object property.
Yes, you can do that with strings and the Reflection API now - the point is
not whether or not it can already be done, the point is to make it part of
the language, so that you can use it based on more than just ideas and
assumptions, and so we can build libraries and applications with proper IDE
support.
Current codebases rely heavily on conventions and APIs - many popular
meta-programming techniques could be simplified and made more elegant,
easier to understand without having to learn conventions, faster to use,
and with support for static analysis.
- Rasmus Schultz
On Thu, Apr 25, 2013 at 2:47 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Okay,
No one seemed extremely interested in my notes about static
type-referenceshttp://marc.info/?t=136327849600002&r=1&w=2- I wantto 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 referencedpublic 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
Maybe I didn't understand what you mean, but if you want property
references, why not just use, well, property references?function foo(&$ref) { $ref = 'a'; }
$a = new Obj;
foo($a->prop);
var_dump($a->prop) // string(1) "a"Also works for magic properties, assuming your correctly declared them
using &__get.If you want more than just get/set, but also info on the property, why not
pass a ReflectionProperty or a modification thereof which has a pre-bound
object? Why do you need a new operator for this?Nikita
Hi Rasmus,
Am 25.04.2013 um 14:47 schrieb Rasmus Schultz rasmus@mindplay.dk:
[...]
What do you think?
I'm not sure about the operator character but the general idea is a good one. Do you have a patch as a POC?
cu,
Lars
The characters was an arbitrary choice, just for the sake of argument.
I'm not a C programmer, so I don't have a patch - there is also no RFC, but
there is general interest, I'd be happy to write one.
Hi Rasmus,
Am 25.04.2013 um 14:47 schrieb Rasmus Schultz rasmus@mindplay.dk:
[...]What do you think?
I'm not sure about the operator character but the general idea is a good
one. Do you have a patch as a POC?cu,
Lars
The characters was an arbitrary choice, just for the sake of argument.
I'm not a C programmer, so I don't have a patch - there is also no RFC, but
there is general interest, I'd be happy to write one.Hi Rasmus,
Am 25.04.2013 um 14:47 schrieb Rasmus Schultz rasmus@mindplay.dk:
[...]What do you think?
I'm not sure about the operator character but the general idea is a good
one. Do you have a patch as a POC?
Do you mean something yucky like http://pecl.php.net/propro?
It's actually been meant to be used by extensions for internal properties,
but it might do the evil you're looking for.
--
Regards,
Mike
Do you mean something yucky like http://pecl.php.net/propro?
I don't know what that is, and there is no description on that page.
It's actually been meant to be used by extensions for internal properties,
but it might do the evil you're looking for.
Would you care to elaborate? What is evil about the thing I've described?
The characters was an arbitrary choice, just for the sake of argument.
I'm not a C programmer, so I don't have a patch - there is also no RFC,
but
there is general interest, I'd be happy to write one.Hi Rasmus,
Am 25.04.2013 um 14:47 schrieb Rasmus Schultz rasmus@mindplay.dk:
[...]What do you think?
I'm not sure about the operator character but the general idea is a good
one. Do you have a patch as a POC?Do you mean something yucky like http://pecl.php.net/propro?
It's actually been meant to be used by extensions for internal properties,
but it might do the evil you're looking for.--
Regards,
Mike
2013.04.30. 14:00, "Rasmus Schultz" rasmus@mindplay.dk ezt írta:
Do you mean something yucky like http://pecl.php.net/propro?
I don't know what that is, and there is no description on that page.
you can grasp the concept from the testcase:
http://git.php.net/?p=pecl/php/propro.git;a=blob_plain;f=tests/001.phpt;hb=HEAD
That looks more pointless than evil to me - and no, I'm not suggesting
anything of that sort.
I'm proposing we need a way to statically reference an object property -
the object property itself, not it's value:
var_dump($user->name); // => 'Rasmus'
var_dump(^$user->name); // => PropertyReference(class: 'User',
propertyName: 'name', object:User(...))
$foo = ^$user->name;
var_dump($foo->getValue()); // => 'Rasmus'
$foo->setValue('Bob');
var_dump($user->name); // => 'Bob'
Is that easier to understand?
- Rasmus Schultz
2013.04.30. 14:00, "Rasmus Schultz" rasmus@mindplay.dk ezt írta:
Do you mean something yucky like http://pecl.php.net/propro?
I don't know what that is, and there is no description on that page.
you can grasp the concept from the testcase:
http://git.php.net/?p=pecl/php/propro.git;a=blob_plain;f=tests/001.phpt;hb=HEAD
Just an idea: why not also use ^ (or another operator) to access the
value? (maybe as an additional way to get/setValue)
$foo = ^$user->name;
echo 'Hello '.^$foo;
^$foo = 'Bob';
(using the same operator will conflict when you are accessing a
property of an object which is a PropertyReference)
I don't think that's necessary - the point of being able to do this, is to
apply meta-programming techniques, so in most situations, what matters is
the ability to quickly create object/property-references... using them will
usually happen inside some service component, e.g. a form-helper or
object/relational-mapper. Having a short syntax for that is much less
relevant - what matters if easy (and of course static) creation of
references to those objects/properties.
Just an idea: why not also use ^ (or another operator) to access the
value? (maybe as an additional way to get/setValue)$foo = ^$user->name;
echo 'Hello '.^$foo;
^$foo = 'Bob';(using the same operator will conflict when you are accessing a
property of an object which is a PropertyReference)
Hi!
I'm proposing we need a way to statically reference an object property -
the object property itself, not it's value:
You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
I'm proposing we need a way to statically reference an object property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.
It is certainly not worth overloading the XOR operator for.
-Rasmus
2013/4/30 Rasmus Lerdorf rasmus@lerdorf.com
Hi!
I'm proposing we need a way to statically reference an object property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.It is certainly not worth overloading the XOR operator for.
-Rasmus
In C#, they had the intention to introduce the operator infoof(...) to get
the reflection, not only of properties, but of virtually everything in the
language. They abandoned the idea because it is really hard to do that for
overloaded functions and they did not want to do all that work for a half
baked feature:
http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
However, PHP does not have overloaded functions, which makes things
significantly easier, so maybe it is worth examining the idea.
Lazare INEPOLOGLOU
Ingénieur Logiciel
Hi!
In C#, they had the intention to introduce the operator infoof(...) to
get the reflection, not only of properties, but of virtually everything
in the language. They abandoned the idea because it is really hard to do
that for overloaded functions and they did not want to do all that work
for a half baked feature:http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
However, PHP does not have overloaded functions, which makes things
significantly easier, so maybe it is worth examining the idea.
PHP has functions that can be result of __call or arbitrary code that
implements fcall handler in an extension. What would be returned then?
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hello,
2013/5/1 Stas Malyshev smalyshev@sugarcrm.com
Hi!
In C#, they had the intention to introduce the operator infoof(...) to
get the reflection, not only of properties, but of virtually everything
in the language. They abandoned the idea because it is really hard to do
that for overloaded functions and they did not want to do all that work
for a half baked feature:http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
However, PHP does not have overloaded functions, which makes things
significantly easier, so maybe it is worth examining the idea.PHP has functions that can be result of __call or arbitrary code that
implements fcall handler in an extension. What would be returned then?
The result is the same with "new ReplectionMethod('foo','bar')". The added
value is that it can be statically checked.
Lazare INEPOLOGLOU
Ingénieur Logiciel
I suggested something similar earlier:
http://marc.info/?t=136327849600002&r=1&w=2
However, I withdrew that idea, because I came to the realization that, for
practical applications, you usually need the object-context coupled with
the member-reference to do anything really useful.
A form-input abstraction, for example, needs the object-context to reflect
on the class, the property-reference to reflect on annotations (maybe) and
of course the property-value, plus the ability to apply a posted value back
onto to the object-property.
The proposed feature facilitates all of that.
At the risk of starting a separate discussion, the recently added
ClassName::class constant provides a way to statically reference a class,
which frankly has very few practical applications in comparison - the need
to reference properties is usually much more prevalent and repetitive than
the need to reference a class; assuming your classes have more than one
property each, heh. The feature as such is also somewhat crippled, since
what comes out of it is a string and not a class-reference.
It solves the problems of static class-references of course, so that's
positive - but where's the much more critical property-reference
counterpart? Because this feature overloads class-constant syntax, there is
no obvious counterpart for properties. It seems pretty short-sighted. If
referencing a class statically is necessary and important enough to make it
into the language, why are property-references considered less important or
valuable?
Try to think of these features in terms of completing or complementing the
fairly limited static side of an otherwise mostly dynamic language, rather
than as features intended to solve a specific programming problem as such.
I think there is still a pretty strong case for static property-references,
but since any new language-feature is generally a pretty hard sell around
here, I'm letting this one go for now.
The immediate impact and benefits of static object-property references
ought to be a much easier sell - it has pretty broad applications, and can
probably replace a lot of simple inline function-closures, and eliminate a
lot of double-arguments (object and property-name) from many
popular/mainstream libraries.
If you disagree, please explain by example. I've already put a lot of time
into thinking about this and explaining it pretty carefully. If you're
opposed for more than personal reasons, surely you can offer more than a
flippant one-line backlash? :-)
On Tue, Apr 30, 2013 at 6:20 PM, Lazare Inepologlou linepogl@gmail.comwrote:
2013/4/30 Rasmus Lerdorf rasmus@lerdorf.com
Hi!
I'm proposing we need a way to statically reference an object property
the object property itself, not it's value:
You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.It is certainly not worth overloading the XOR operator for.
-Rasmus
In C#, they had the intention to introduce the operator infoof(...) to get
the reflection, not only of properties, but of virtually everything in the
language. They abandoned the idea because it is really hard to do that for
overloaded functions and they did not want to do all that work for a half
baked feature:http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
However, PHP does not have overloaded functions, which makes things
significantly easier, so maybe it is worth examining the idea.Lazare INEPOLOGLOU
Ingénieur Logiciel
At the risk of starting a separate discussion, the recently added
ClassName::class constant provides a way to statically reference a class,
which frankly has very few practical applications in comparison - the need
to reference properties is usually much more prevalent and repetitive than
the need to reference a class; assuming your classes have more than one
property each, heh. The feature as such is also somewhat crippled, since
what comes out of it is a string and not a class-reference.
I would caution against generalising use cases. Personally, ::class is
something I can use multiple times a day. This I'm not so sure about.
Your use case is not my use case, and vice versa. :)
I think there is still a pretty strong case for static property-references,
but since any new language-feature is generally a pretty hard sell around
here, I'm letting this one go for now.
Why does this have to be a language feature? It obviously already
works in userland, as your own Symfony 2 examples show. One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.
Adam
I would caution against generalising use cases. Personally, ::class is
something I can use multiple times a day. This I'm not so sure about.Your use case is not my use case, and vice versa. :)
What is your use-case then? DI perhaps?
Why does this have to be a language feature?
I already covered that.
It obviously already works in userland, as your own Symfony 2 examples
show.
As explained, this is not intended to solve a problem that can't currently
by solved by other means, but to strengthen the static aspects of the
language.
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.
Look at the Symfony form-builder example - encapsulating the indirection is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.
Yes, you can already create property-references at run-time - for that
matter, you could already use new ReflectionProperty($obj, 'prop') to do
what you demonstrated above.
But the property-name, in the source-code, is a string - it has no literal
relationship to YourClass::$prop where as ^$obj->prop does.
No mainstream framework provides a PropertyReference class, because it
wouldn't accomplish anything - the property-name is still a string, it's
still unchecked, and still can't (reliably) be used in static analysis.
2013/5/1 Rasmus Schultz rasmus@mindplay.dk
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.Look at the Symfony form-builder example - encapsulating the indirection is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.
As the developer of the Symfony Form component, I would like to clarify
that this is not true. At the time the property reference is stored, the
object it refers to is not (necessarily) known. You could build an abstract
form definition for "Author" instances, but only later instantiate a form
for that definition with a concrete object. So to be really useful in a
form context, property references need to be separated from object
instances (something like "^Author::$firstName" could work).
Second, it is important that references can span multiple nodes in an
object/array graph. In Symfony, we built the PropertyAccess component for
that [1] which allows references like
"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
or
->authors[0]->getPersonalDetails()['firstName']
etc., depending on whether accessors exist or the properties themselves are
public (also works for writing values). This is a concept borrowed from
Java and known as "property paths". [2] Without the possibility of
chaining, property references are useless IMO.
Cheers,
Bernhard
[1]
http://symfony.com/doc/current/components/property_access/introduction.html
[2]
http://static.springsource.org/spring-data/data-commons/docs/1.3.0.M1/api/org/springframework/data/mapping/PropertyPath.html
"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
It's indirection via strings.
This particular example isn't great for what I'm proposing, because you're
not accessing a property - using an array-index, you get a value. There is
no property - hence nothing to reflect on.
Assuming you have accessors for those get() and set() methods, and assuming
$firstName is an object-property and not just a hashed string, why not
simply:
$p = ^$authors[0]->personalDetails->firstName;
Assuming you added static information about the type of $authors, what was
previously a string (for which you need a run-time parser and a bunch of
code) is now IDE-friendly, with auto-completion as you type, inspections,
accurate refactoring, etc. (without writing framework-specific plug-ins for
every major IDE.)
If $authors is an array, this might translate roughly into:
$p = new PropertyReference($authors[0]->personalDetails, 'firstName');
Or perhaps with more lazy evaluation:
$p = new PropertyReference(
function () use (&$authors) {
return $authors[0]->personalDetails;
}
,
'firstName'
);
It's still dynamic, but the source-code now contains more static
information - you're using PHP syntax instead of inventing custom syntax
and parsing it out of strings, for things the language can already do, but
doesn't do elegantly.
You now have the ability to reflect on the type of the $personalDetails
object and the $firstName property and establish defaults based on
annotation parsing (as as popular in Symfony) or conventions for labels
('firstName' => 'First Name') etc.
You can assert early on if this code is going to work. You can know if you
making a break change somewhere along that object graph. You don't need a
library to parse custom syntax for value paths at run-time anymore, you're
not inventing new syntax for something the language can already do, and
developers no longer need to learn that custom syntax. You can use
automated refactoring. Your IDE can provide auto-complete and inline
documentation as you type.
I don't like strings for references to source-code elements. It's ugly,
it's unsafe, it can't be analyzed or refactored, and it's bloody backwards
- to use a different example, look at this oddly popular approach to
configuration:
$config = array(
'foo' => 'bar',
'services' => array(
'db' => array(
'username' => '...',
'password' => '...',
),
'email' => array(
'host' => '....',
),
),
);
Those are not objects and properties, they are arrays and strings, and they
are dead matter.
But they map 1:1 to objects and properties.
So for all intents and purposes, they are a dead form of objects and
properties that can only be revived at run-time - nothing can be known
about the existence of any of those objects or properties prior to actually
running the code. That means you can expect some ugly surprises down the
line, when one of these unchecked references turn out to be wrong, or some
change/refactoring breaks code that worked before. Or you can spend a lot
of time writing unit-tests for things that shouldn't be able to fail in the
first place.
There are ways around that, and it involves relying on the static qualities
of the language:
$config[] = function (PDO $db) {
$db->username = 'foo';
$db->password = 'bar';
};
Thanks to the type-hint - a popular static language feature - this code can
inspected and checked.
If you wanted the same for your nested arrays and strings, you would have
to write plug-ins for every major IDE - more code.
I like simple things. That's one of the key reasons I like PHP.
Dynamic is not automatically simpler. Especially not when you have to learn
and write and maintain oodles of static source-code annotations to bring
the code-quality up to a level that is accepted by the PHP community at
large.
If you think keeping the language simple makes life simpler, you're fooling
yourself.
It's good that people like Bernhard have the time and energy to come up
with solutions to problems like these - it's bad when we have to resort to
unchecked code and custom syntax and parsers and IDE plug-ins to solve
these problems and work comfortably with those solutions.
Exclusively static languages aren't the answer, but neither are dominantly
dynamic languages - the majority of PHP code is heavily embedded with
static information for a reason.
I would never want to see the dynamic features of the language crippled or
encumbered in favor of static features - but to ignore the need for more
static features in the language is to hold back a natural development that
is already happening whether you approve of it or not.
Maybe this particular feature is wrong for other reasons, I don't know,
that's why we're discussing it.
But don't reject the idea because it's static and doesn't fit with your
ideas of a dynamic language.
On Thu, May 2, 2013 at 9:06 AM, Bernhard Schussek bschussek@gmail.comwrote:
2013/5/1 Rasmus Schultz rasmus@mindplay.dk
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.Look at the Symfony form-builder example - encapsulating the indirection
is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.As the developer of the Symfony Form component, I would like to clarify
that this is not true. At the time the property reference is stored, the
object it refers to is not (necessarily) known. You could build an abstract
form definition for "Author" instances, but only later instantiate a form
for that definition with a concrete object. So to be really useful in a
form context, property references need to be separated from object
instances (something like "^Author::$firstName" could work).Second, it is important that references can span multiple nodes in an
object/array graph. In Symfony, we built the PropertyAccess component for
that [1] which allows references like"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
or
->authors[0]->getPersonalDetails()['firstName']
etc., depending on whether accessors exist or the properties themselves
are public (also works for writing values). This is a concept borrowed from
Java and known as "property paths". [2] Without the possibility of
chaining, property references are useless IMO.Cheers,
Bernhard[1]
http://symfony.com/doc/current/components/property_access/introduction.html
[2]
http://static.springsource.org/spring-data/data-commons/docs/1.3.0.M1/api/org/springframework/data/mapping/PropertyPath.html
Oh, here's a thought: let's just throw more annotations at it?
$config = /** @ref AppConfiguration / array(
'services' => /* @ref ServiceContainer / array(
/* @ref PDO */ array(
'username' => 'foo',
'password' => 'bar',
)
),
);
This would work - it would instruct a static analyzer that the keys in
those arrays are actually references to properties, and you could then
autocomplete the strings and property-names, display inline documentation,
perform inspections, etc.
The same would work in form-helpers:
echo $form->textInput(/** @ref User */ 'email');
Auto-complete, auto-refactoring, all possible now.
It looks horrible of course, and pretty soon we'll be extending our
annotation-parsers to get access to the static information embedded in
doc-blocks that isn't part of the language.
It's not very elegant, because it addresses a problem, but ignores the
underlying root of the problem. It treats a symptom, not the cause. (the
staple of American over-priced inferior health care, or perhaps more
accurately, "sick care".)
I really like to see programming languages addressing problems at the root.
We should look below every need and every problem to find the simplest
possible solution that best addresses the broadest possible set of problems.
Maybe this feature doesn't do that. But then let's ponder what does?
There has got to be ways in which the language can better facilitate things
like property indirection and other needs for more static features?
And I don't believe that will ruin the experience or bump the learning
curve for an otherwise very accessible language - seeing as how everyone
has to learn how to decorate their code with static information sooner or
later.
PHP is being used for much bigger things these days than just forums and
blogs - it's driving big applications and services.
You don't think it's possible to elevate the language to a level where it
can facilitate complex architecture as well as simple forums and blogs?
You've made strides these past few years, you really have. Please don't
quit or think you're all done? :-)
"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
It's indirection via strings.
This particular example isn't great for what I'm proposing, because you're
not accessing a property - using an array-index, you get a value. There is
no property - hence nothing to reflect on.Assuming you have accessors for those get() and set() methods, and
assuming $firstName is an object-property and not just a hashed string, why
not simply:$p = ^$authors[0]->personalDetails->firstName;
Assuming you added static information about the type of $authors, what was
previously a string (for which you need a run-time parser and a bunch of
code) is now IDE-friendly, with auto-completion as you type, inspections,
accurate refactoring, etc. (without writing framework-specific plug-ins for
every major IDE.)If $authors is an array, this might translate roughly into:
$p = new PropertyReference($authors[0]->personalDetails, 'firstName');
Or perhaps with more lazy evaluation:
$p = new PropertyReference( function () use (&$authors) { return $authors[0]->personalDetails; } , 'firstName' );
It's still dynamic, but the source-code now contains more static
information - you're using PHP syntax instead of inventing custom syntax
and parsing it out of strings, for things the language can already do, but
doesn't do elegantly.You now have the ability to reflect on the type of the $personalDetails
object and the $firstName property and establish defaults based on
annotation parsing (as as popular in Symfony) or conventions for labels
('firstName' => 'First Name') etc.You can assert early on if this code is going to work. You can know if you
making a break change somewhere along that object graph. You don't need a
library to parse custom syntax for value paths at run-time anymore, you're
not inventing new syntax for something the language can already do, and
developers no longer need to learn that custom syntax. You can use
automated refactoring. Your IDE can provide auto-complete and inline
documentation as you type.I don't like strings for references to source-code elements. It's ugly,
it's unsafe, it can't be analyzed or refactored, and it's bloody backwards
- to use a different example, look at this oddly popular approach to
configuration:$config = array(
'foo' => 'bar',
'services' => array(
'db' => array(
'username' => '...',
'password' => '...',
),
'email' => array(
'host' => '....',
),
),
);Those are not objects and properties, they are arrays and strings, and
they are dead matter.But they map 1:1 to objects and properties.
So for all intents and purposes, they are a dead form of objects and
properties that can only be revived at run-time - nothing can be known
about the existence of any of those objects or properties prior to actually
running the code. That means you can expect some ugly surprises down the
line, when one of these unchecked references turn out to be wrong, or some
change/refactoring breaks code that worked before. Or you can spend a lot
of time writing unit-tests for things that shouldn't be able to fail in the
first place.There are ways around that, and it involves relying on the static
qualities of the language:$config[] = function (PDO $db) { $db->username = 'foo'; $db->password = 'bar'; };
Thanks to the type-hint - a popular static language feature - this code
can inspected and checked.If you wanted the same for your nested arrays and strings, you would have
to write plug-ins for every major IDE - more code.I like simple things. That's one of the key reasons I like PHP.
Dynamic is not automatically simpler. Especially not when you have to
learn and write and maintain oodles of static source-code annotations to
bring the code-quality up to a level that is accepted by the PHP community
at large.If you think keeping the language simple makes life simpler, you're
fooling yourself.It's good that people like Bernhard have the time and energy to come up
with solutions to problems like these - it's bad when we have to resort to
unchecked code and custom syntax and parsers and IDE plug-ins to solve
these problems and work comfortably with those solutions.Exclusively static languages aren't the answer, but neither are dominantly
dynamic languages - the majority of PHP code is heavily embedded with
static information for a reason.I would never want to see the dynamic features of the language crippled or
encumbered in favor of static features - but to ignore the need for more
static features in the language is to hold back a natural development that
is already happening whether you approve of it or not.Maybe this particular feature is wrong for other reasons, I don't know,
that's why we're discussing it.But don't reject the idea because it's static and doesn't fit with your
ideas of a dynamic language.On Thu, May 2, 2013 at 9:06 AM, Bernhard Schussek bschussek@gmail.comwrote:
2013/5/1 Rasmus Schultz rasmus@mindplay.dk
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.Look at the Symfony form-builder example - encapsulating the indirection
is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.As the developer of the Symfony Form component, I would like to clarify
that this is not true. At the time the property reference is stored, the
object it refers to is not (necessarily) known. You could build an abstract
form definition for "Author" instances, but only later instantiate a form
for that definition with a concrete object. So to be really useful in a
form context, property references need to be separated from object
instances (something like "^Author::$firstName" could work).Second, it is important that references can span multiple nodes in an
object/array graph. In Symfony, we built the PropertyAccess component for
that [1] which allows references like"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
or
->authors[0]->getPersonalDetails()['firstName']
etc., depending on whether accessors exist or the properties themselves
are public (also works for writing values). This is a concept borrowed from
Java and known as "property paths". [2] Without the possibility of
chaining, property references are useless IMO.Cheers,
Bernhard[1]
http://symfony.com/doc/current/components/property_access/introduction.html
[2]
http://static.springsource.org/spring-data/data-commons/docs/1.3.0.M1/api/org/springframework/data/mapping/PropertyPath.html
2013/5/2 Bernhard Schussek bschussek@gmail.com
2013/5/1 Rasmus Schultz rasmus@mindplay.dk
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.Look at the Symfony form-builder example - encapsulating the indirection
is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.As the developer of the Symfony Form component, I would like to clarify
that this is not true. At the time the property reference is stored, the
object it refers to is not (necessarily) known. You could build an abstract
form definition for "Author" instances, but only later instantiate a form
for that definition with a concrete object. So to be really useful in a
form context, property references need to be separated from object
instances (something like "^Author::$firstName" could work).Second, it is important that references can span multiple nodes in an
object/array graph. In Symfony, we built the PropertyAccess component for
that [1] which allows references like"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
or
->authors[0]->getPersonalDetails()['firstName']
I have an idea regarding the syntax. The suggested ^ operator is
troublesome, because it does not make clear that whatever follows will not
be evaluated. This becomes even more confusing when dealing with multiple
nodes, as the example above, where part of the expression has to be
evaluated.
Let's have something different:
$obj~>property
MyClass::~property
This syntax can be easily applied to multiple nodes, without confusion:
->getAuthors()[0]->getPersonalDetails()~>firstName
And it can be applied statically:
Author::~firstName
Lazare Inepologlou
Ingénieur Logiciel
That's an interesting spin on the idea, but it takes away the ability to
lazy-evaluate an entire path - now it works only for the last property,
which may not always be optimal or desirable.
I don't personally have a problem with putting the operator before the
expression, I think that's clear enough - it's clear enough for the // and
comment operators, for example, that the entire line will be commented
out.
If you don't agree with that, maybe it should be a grouping operator, e.g.
a start and an end symbol? Even harder to find characters that won't
conflict though...
On Fri, May 3, 2013 at 4:24 AM, Lazare Inepologlou linepogl@gmail.comwrote:
2013/5/2 Bernhard Schussek bschussek@gmail.com
2013/5/1 Rasmus Schultz rasmus@mindplay.dk
One could
write a PropertyReference class right now with literally the only
difference being the lack of a builtin operator (ie new
PropertyReference($obj, 'prop') versus ^$obj->prop): the fact that
nobody seems to have done this in a major framework I know of suggests
that there isn't a strong need for encapsulating the indirection
beyond the $obj->$prop syntax that's worked forever.Look at the Symfony form-builder example - encapsulating the
indirection is
precisely what they're doing: the object reference is stored in the
form-builder, and property-names are added subsequently.As the developer of the Symfony Form component, I would like to clarify
that this is not true. At the time the property reference is stored, the
object it refers to is not (necessarily) known. You could build an
abstract
form definition for "Author" instances, but only later instantiate a form
for that definition with a concrete object. So to be really useful in a
form context, property references need to be separated from object
instances (something like "^Author::$firstName" could work).Second, it is important that references can span multiple nodes in an
object/array graph. In Symfony, we built the PropertyAccess component for
that [1] which allows references like"authors[0].personalDetails[firstName]"
which translates to
->getAuthors()[0]->getPersonalDetails()['firstName']
or
->authors[0]->getPersonalDetails()['firstName']
I have an idea regarding the syntax. The suggested ^ operator is
troublesome, because it does not make clear that whatever follows will not
be evaluated. This becomes even more confusing when dealing with multiple
nodes, as the example above, where part of the expression has to be
evaluated.Let's have something different:
$obj~>property
MyClass::~propertyThis syntax can be easily applied to multiple nodes, without confusion:
->getAuthors()[0]->getPersonalDetails()~>firstName
And it can be applied statically:
Author::~firstName
Lazare Inepologlou
Ingénieur Logiciel
That's an interesting spin on the idea, but it takes away the ability to
lazy-evaluate an entire path - now it works only for the last property,
which may not always be optimal or desirable.I don't personally have a problem with putting the operator before the
expression, I think that's clear enough - it's clear enough for the // andcomment operators, for example, that the entire line will be commented
out.
If you don't agree with that, maybe it should be a grouping operator, e.g.
a start and an end symbol? Even harder to find characters that won't
conflict though...
Hey Rasmus!
Rather than continuing this discussion, could you please create an RFC
which summarizes your proposal, what it offers to PHP and maybe also what
arguments people had against it? I have neither the time nor the motivation
to read through 50 rather lengthy mails in order to figure out what this is
about. Also discussion usually goes into a more constructive direction once
more people can chime in (rather than just rehashing the same arguments
among a few participants).
Thanks,
Nikita
Any PHP dev who works with a mainstream framework does this daily, but the
frameworks rely on strings for property-names.
Take this example from the Symfony manual, for example:
class Task
{
protected $task;
protected $dueDate;
public function getTask()
{
return $this->task;
}
public function setTask($task)
{
$this->task = $task;
}
public function getDueDate()
{
return $this->dueDate;
}
public function setDueDate(\DateTime $dueDate = null)
{
$this->dueDate = $dueDate;
}
}
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
In this example, 'task' and 'dueDate' are property-references - except of
course that, no, they're not - they're obviously just strings... rewriting
this example to use a (fictive) form builder API with static
property-references:
$form = $this->createFormBuilder()
->add(^$task->task, 'text')
->add(^$task->dueDate, 'date')
->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic refactoring
for operations like renaming properties, etc.
Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.
For that matter, we can now scrap the form-builder entirely and introduce a
simple form-helper in the view instead:
Task name: <?= $form->textInput(^$task->task) ?>
Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support and
static analysis for textInput() and dateInput() which were previously
unchecked strings.
Or even simpler:
Task name: <?= $form->input(^$task->task) ?>
Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but use
of annotations in Symfony is pretty popular.
This is just one example - most PHP devs (at least those who do PHP for a
living) use form abstractions and object/relational-mappers of some sort,
so this has practical applications for practically everyone, everywhere.
Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.
On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
I'm proposing we need a way to statically reference an object property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
Any PHP dev who works with a mainstream framework does this daily, but
the frameworks rely on strings for property-names.
What's wrong with strings? Just because it doesn't have three levels of
objects on it, doesn't mean it's not OK to use it.
We now have static property-references, which means the codebase can be
If you know the property, you can just access it, you don't need to
invent weird indirection for it.
Are we really going to quibble about syntax? This adds nothing to this
We're going to quibble about again trying to bring very small scope and
exotic feature into the core of the language.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
I've already demonstrated and explained what's wrong with strings.
"Weird indirection" is what we have in every mainstream framework right
now, where properties can be referenced only as strings - I gave a
real-world example of this, and demonstrated with a practical example how
the proposed feature can help improve on this issue.
I've demonstrated by example that this has more than limited scope.
The fact that mainstream frameworks have to resort to strings for
property-references is a symptom of the fact that this feature is absent:
-
Mainstream frameworks already do what I propose (using strings)
demonstrating that it is a necessary task. -
People use these frameworks - proving that developers want these features
from the frameworks they use.
Please, contribute something material to this discussion - your snappy
responses have to make me think you're taking this very personally?
I promise I'm not trying to ruin your day. Can't we just have a friendly
discussion like grown-ups?
On Tue, Apr 30, 2013 at 7:16 PM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
Any PHP dev who works with a mainstream framework does this daily, but
the frameworks rely on strings for property-names.What's wrong with strings? Just because it doesn't have three levels of
objects on it, doesn't mean it's not OK to use it.We now have static property-references, which means the codebase can be
If you know the property, you can just access it, you don't need to
invent weird indirection for it.Are we really going to quibble about syntax? This adds nothing to this
We're going to quibble about again trying to bring very small scope and
exotic feature into the core of the language.Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
> Any PHP dev who works with a mainstream framework does this daily, but the
> frameworks rely on strings for property-names.
>
> Take this example from the Symfony manual, for example:
>
>
> class Task
> {
> protected $task;
>
> protected $dueDate;
>
> public function getTask()
> {
> return $this->task;
> }
> public function setTask($task)
> {
> $this->task = $task;
> }
>
> public function getDueDate()
> {
> return $this->dueDate;
> }
> public function setDueDate(\DateTime $dueDate = null)
> {
> $this->dueDate = $dueDate;
> }
> }
>
> $form = $this->createFormBuilder($task)
> ->add('task', 'text')
> ->add('dueDate', 'date')
> ->getForm();
>
> In this example, 'task' and 'dueDate' are property-references - except of
> course that, no, they're not - they're obviously just strings... rewriting
> this example to use a (fictive) form builder API with static
> property-references:
>
> $form = $this->createFormBuilder()
> ->add(^$task->task, 'text')
> ->add(^$task->dueDate, 'date')
> ->getForm();
>
One problem I have with this example is, that you usually (or at least
often) don't have a "$task" object here.
>
> We now have static property-references, which means the codebase can be
> proofed using static analysis, which also means better IDE support with
> property auto-completion, inline documentation, and automatic refactoring
> for operations like renaming properties, etc.
>
> Note that $task need not be passed to createFormBuilder() anymore -
> instead, we can now use PropertyReference::getObject() inside the
> form-builder to obtain the instance.
>
> For that matter, we can now scrap the form-builder entirely and introduce a
> simple form-helper in the view instead:
>
> Task name: <?= $form->textInput(^$task->task) ?>
> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
>
> This is even better, because we now have the same level of IDE support and
> static analysis for textInput() and dateInput() which were previously
> unchecked strings.
>
> Or even simpler:
>
> Task name: <?= $form->input(^$task->task) ?>
> Due Date: <?= $form->input(^$task->dueDate) ?>
>
> Using PropertyReference::getObject() and reflection inside the
> form-helper's input() method, we can now use property-annotations to
> specify the input-type. This is a matter of preference of course, but use
> of annotations in Symfony is pretty popular.
>
> This is just one example - most PHP devs (at least those who do PHP for a
> living) use form abstractions and object/relational-mappers of some sort,
> so this has practical applications for practically everyone, everywhere.
>
> Rasmus Lerdorf wrote:
>
> It is certainly not worth overloading the XOR operator for
>
>
> Are we really going to quibble about syntax? This adds nothing to this
> discussion. And as I explained earlier, the ^ operator is used for the sake
> of discussion only - if it's more practical to use another character for
> this operator, I don't care what it looks like.
>
>
> On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev
>
> > Hi!
> >
> > > I'm proposing we need a way to statically reference an object property
> -
> > > the object property itself, not it's value:
> >
> > You probably have use case for that, and it should be pretty easy to
> > write a class that does that, but why it should be in the language? It
> > certainly doesn't look like something sizeable portion of PHP devs would
> > do frequently.
> >
> > --
> > Stanislav Malyshev, Software Architect
> > SugarCRM: http://www.sugarcrm.com/
> > (408)454-6900 ext. 227
> >
>
--
github.com/KingCrunch
> one problem I have with this example is, that you usually (or at least
> often) don't have a "$task" object here.
I get what you're saying, but you do have a $task object if you want to use
the form-builder, because it relies on the object for state.
The same is true for most frameworks, and not generally a problem, since
you can just create a transient (throw-away) object - this generally works
fine, and has the added benefit of being able to initialize object
properties with defaults. (such as today's date on a calendar entry form)
On Tue, Apr 30, 2013 at 7:50 PM, Sebastian Krebs
>
>
>
> 2013/5/1 Rasmus Schultz
>
>> Any PHP dev who works with a mainstream framework does this daily, but the
>> frameworks rely on strings for property-names.
>>
>> Take this example from the Symfony manual, for example:
>>
>>
>> class Task
>> {
>> protected $task;
>>
>> protected $dueDate;
>>
>> public function getTask()
>> {
>> return $this->task;
>> }
>> public function setTask($task)
>> {
>> $this->task = $task;
>> }
>>
>> public function getDueDate()
>> {
>> return $this->dueDate;
>> }
>> public function setDueDate(\DateTime $dueDate = null)
>> {
>> $this->dueDate = $dueDate;
>> }
>> }
>>
>> $form = $this->createFormBuilder($task)
>> ->add('task', 'text')
>> ->add('dueDate', 'date')
>> ->getForm();
>>
>> In this example, 'task' and 'dueDate' are property-references - except of
>> course that, no, they're not - they're obviously just strings... rewriting
>> this example to use a (fictive) form builder API with static
>> property-references:
>>
>> $form = $this->createFormBuilder()
>> ->add(^$task->task, 'text')
>> ->add(^$task->dueDate, 'date')
>> ->getForm();
>>
>
> One problem I have with this example is, that you usually (or at least
> often) don't have a "$task" object here.
>
>
>
>>
>> We now have static property-references, which means the codebase can be
>> proofed using static analysis, which also means better IDE support with
>> property auto-completion, inline documentation, and automatic refactoring
>> for operations like renaming properties, etc.
>>
>> Note that $task need not be passed to createFormBuilder() anymore -
>> instead, we can now use PropertyReference::getObject() inside the
>> form-builder to obtain the instance.
>>
>> For that matter, we can now scrap the form-builder entirely and introduce
>> a
>> simple form-helper in the view instead:
>>
>> Task name: <?= $form->textInput(^$task->task) ?>
>> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
>>
>> This is even better, because we now have the same level of IDE support and
>> static analysis for textInput() and dateInput() which were previously
>> unchecked strings.
>>
>> Or even simpler:
>>
>> Task name: <?= $form->input(^$task->task) ?>
>> Due Date: <?= $form->input(^$task->dueDate) ?>
>>
>> Using PropertyReference::getObject() and reflection inside the
>> form-helper's input() method, we can now use property-annotations to
>> specify the input-type. This is a matter of preference of course, but use
>> of annotations in Symfony is pretty popular.
>>
>> This is just one example - most PHP devs (at least those who do PHP for a
>> living) use form abstractions and object/relational-mappers of some sort,
>> so this has practical applications for practically everyone, everywhere.
>>
>> Rasmus Lerdorf wrote:
>>
>> It is certainly not worth overloading the XOR operator for
>>
>>
>> Are we really going to quibble about syntax? This adds nothing to this
>> discussion. And as I explained earlier, the ^ operator is used for the
>> sake
>> of discussion only - if it's more practical to use another character for
>> this operator, I don't care what it looks like.
>>
>>
>> On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev
>>
>> > Hi!
>> >
>> > > I'm proposing we need a way to statically reference an object
>> property -
>> > > the object property itself, not it's value:
>> >
>> > You probably have use case for that, and it should be pretty easy to
>> > write a class that does that, but why it should be in the language? It
>> > certainly doesn't look like something sizeable portion of PHP devs would
>> > do frequently.
>> >
>> > --
>> > Stanislav Malyshev, Software Architect
>> > SugarCRM: http://www.sugarcrm.com/
>> > (408)454-6900 ext. 227
>> >
>>
>
>
>
> --
> github.com/KingCrunch
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.
The point is that there is no operator that fits and the reason you
didn't come up with one that didn't clash with something else. If this
can even be implemented, which doesn't seem all that certain without a
lot of messy changes, it should just be a reflection call.
-Rasmus
Okay, that is a technical/implementation problem - and I'm not the guy who
can answer than question.
I was thinking there might be a mathematical (or other) operator that
doesn't work without something in front of it to operate on, and I chose
the ^ operator based on a wild guess, plus the following:
php -r "var_dump(4 ^ 8);"
int(12)
php -r "var_dump(^ 8);"
Parse error: syntax error, unexpected '^', expecting ')' in Command line
code on line 1
php -r "$foo = ^ 8;"
Parse error: syntax error, unexpected '^' in Command line code on line 1
I don't know the parser guts, but I figured since using the ^ operator with
nothing to operate on, causes a parser-error, that means the parser knows
that this is currently not valid syntax? Which might mean that there's a
way to turn this into valid syntax? I don't know.
I also figured the ambiguity with a bitwise operator is minimal damage -
bitwise operators are not one of the most commonly used features in
high-level languages.
If the asterisk (or some other character) offers and easier implementation
path, whatever.
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.The point is that there is no operator that fits and the reason you
didn't come up with one that didn't clash with something else. If this
can even be implemented, which doesn't seem all that certain without a
lot of messy changes, it should just be a reflection call.-Rasmus
If the asterisk (or some other character) offers and easier
implementation path, whatever.
It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure meaning.
But yes, syntax-wise ^ could be made to work, the implementation problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.
-Rasmus
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed
As with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.
Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work
I'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:
$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal PHP
code.
And the PropertyReference class could be implemented in plain PHP like this:
class PropertyReference
{
private $_object;
private $_propertyName;
public function __construct($object, $propertyName)
{
$this->_object = $object;
$this->_propertyName = $propertyName;
}
public function getObject()
{
return $this->_object;
}
public function getPropertyName()
{
return $this->_propertyName;
}
public function getValue()
{
return $this->_object->{$this->_propertyName};
}
public function setValue($value)
{
$this->_object->{$this->_propertyName} = $value;
}
// and maybe:
public function getReflection()
{
return new ReflectionObject($this->_object);
}
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:
http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.
If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure meaning.
But yes, syntax-wise ^ could be made to work, the implementation problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.-Rasmus
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.
Then why are you not convincing them first to get them on board as support
for your proposal. Right now you're obviously fighting an uphill struggle.
Whether that's because your proposal is without merit or because you have a
hard time convincing people on this mailing list remains to be seen - so
how about taking a smarter approach and convincing your target audience
first, then come back here with more support and a better proposal?
Just a thought.
--
<hype>
WWW: plphp.dk / plind.dk
CV: careers.stackoverflow.com/peterlind
LinkedIn: plind
Twitter: kafe15
</hype
Then why are you not convincing them first to get them on board as support
for your proposal.
It's not a proposal yet - I didn't want to write a lengthy RFC just to
learn that all I had was a brainfart, or that everyone was going to be
totally opposed. Having the discussion here surfaced a ton of questions
that (so far) indicate (to me) that this might be a good idea, and also
helps me address all of those questions if I do end up writing an RFC.
If you think gathering the information in an RFC is the next logical step,
I will try to find the time :-)
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.Then why are you not convincing them first to get them on board as support
for your proposal. Right now you're obviously fighting an uphill struggle.
Whether that's because your proposal is without merit or because you have a
hard time convincing people on this mailing list remains to be seen - so
how about taking a smarter approach and convincing your target audience
first, then come back here with more support and a better proposal?Just a thought.
--
<hype>
WWW: plphp.dk / plind.dk
CV: careers.stackoverflow.com/peterlind
LinkedIn: plind
Twitter: kafe15
</hype
Then why are you not convincing them first to get them on board as support
for your proposal.
It's not a proposal yet - I didn't want to write a lengthy RFC just to
learn that all I had was a brainfart, or that everyone was going to be
totally opposed. Having the discussion here surfaced a ton of questions
that (so far) indicate (to me) that this might be a good idea, and also
helps me address all of those questions if I do end up writing an RFC.If you think gathering the information in an RFC is the next logical step,
I will try to find the time :-)
I think that 1) you might as well start the work now, both to give people a
place to get an overview of the discussion and to gather up the questions
of which there are already a few, and that 2) if you don't start by
reaching out to your indicated main audience (frameworks) then you won't
get the support the idea needs. Also, 3) as your indicated audience is
frameworks they will presumably have a lot of feedback - including your
basic "no we don't need this" or "this would be awesome".
Note that I don't think frameworks would necessarily be the sole audience
for this - I just think your time would be better spent taking the idea
there first.
Regards
Peter
--
<hype>
WWW: plphp.dk / plind.dk
CV: careers.stackoverflow.com/peterlind
LinkedIn: plind
Twitter: kafe15
</hype
I know I'm still somewhat of a beginner with OOP, and not at all into large-scale OOP frameworks (yet!), but I'm really struggling to understand why the existing & reference operator doesn't suffice for what you are after?
If you could explain in words of as few syllables as possible what you would want to add to:
class User
{
public $name;
}
$user = new User;
$user->name = 'Rasmus';
$nameprop = &$user->name;
var_dump($nameprop); // => 'Rasmus'
$nameprop = 'Bob';
var_dump($nameprop); // => 'Bob'
I would be immensely grateful, as I might then stand a chance of deciding whether I'm with you or agin you...!
Cheers!
Mike
--
Mike Ford,
Electronic Information Developer, Libraries and Learning Innovation,
Portland PD507, City Campus, Leeds Metropolitan University,
Portland Way, LEEDS, LS1 3HE, United Kingdom
E: m.ford@leedsmet.ac.uk T: +44 113 812 4730
-----Original Message-----
From: Rasmus Schultz [mailto:rasmus@mindplay.dk]
Sent: 01 May 2013 13:35
To: Rasmus Lerdorf
Cc: Stas Malyshev; PHP internals
Subject: Re: [PHP-DEV] property de-referencingThis is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's
hard
to convince anyone they need anything they don't understand - I
think the
barrier here is me having difficulty explaining a new idea/concept.
That
doesn't make it a fringe feature - I have already demonstrated by
example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor
to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop = ^$user-
name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any
normal PHP
code.And the PropertyReference class could be implemented in plain PHP
like this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192b
d3db84ddaf84c83Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd
8e73ff80717f3cbNote that the dynamic User::$name property in this example is
properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact
that you
are having a hard time convincing people that it is needed, and
thus
shouldn't overload an existing operator. Visually it would be
confusing
to take any well-known operator and give it a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't
carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation
could be
found, like I said, adding it to the reflection functions is the
proper
place.-Rasmus
To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop = ^$user->name;
So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static" than
new PropertyReference($user, 'name'), and thus easier to refactor? To me
they really look equivalent from a refactoring point of view.
In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure meaning.
But yes, syntax-wise ^ could be made to work, the implementation problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch
The only reason being that the syntax "^$user->name" is "more static" than
new PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is not.
Refactoring isn't the only benefit - of course most of the benefits are
going to come from IDE support, but would include things like inline
documentation, auto-complete and warnings/errors based on static
analysis/inspections. I already covered that.
PHP-based code-analysis tools would also be able to do a better job when
checking views etc. - if you're using PHP-based static analysis tools to
check for code-smells etc. there's a good chance you have it configured to
skip your view-template folders...
To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working with a
large codebase, and it's error-prone, and therefore requires manual review
of every change before you apply, even for things that should be
quick/simple like renaming a property.
In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?
Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write simpler,
stronger abstractions that provide more comfort and safety in an IDE.
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop = ^$user->name;
So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static" than
new PropertyReference($user, 'name'), and thus easier to refactor? To me
they really look equivalent from a refactoring point of view.In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal
PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure meaning.
But yes, syntax-wise ^ could be made to work, the implementation problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch
The only reason being that the syntax "^$user->name" is "more static" than
new PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is not.
Refactoring isn't the only benefit - of course most of the benefits are
going to come from IDE support, but would include things like inline
documentation, auto-complete and warnings/errors based on static
analysis/inspections. I already covered that.
PHP-based code-analysis tools would also be able to do a better job when
checking views etc. - if you're using PHP-based static analysis tools to
check for code-smells etc. there's a good chance you have it configured to
skip your view-template folders...
I am sorry, but I find very hard to believe that a "^" preceeding a
property access is going to make things easier for any static analysis, and
I have done my share of them.
If you look even at the syntax tree, it is not any harder to track new
ReflectionProperty($obj, "property") than it is to track ^$obj->property,
and that is a fact. You basically have a string literal instead of a
T_STRING.
You might argue that the property name does not need to be a string
literal, but then what about ^$foo->$bar or ^$foo->{'asd'}? would that be
forbidden?
To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working with a
large codebase, and it's error-prone, and therefore requires manual review
of every change before you apply, even for things that should be
quick/simple like renaming a property.
Refactoring in PHP will always be guesswork, error-prone, and will require
manual inspection, whether you have a fancy syntax to create
ReflectionProperies or not. Types are hard to track statically and that
won't change with this. And really, the strict translation of ^$obj->foo is
just as easy (and fast) to track by analyses.
In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?
Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write simpler,
stronger abstractions that provide more comfort and safety in an IDE.
I believe you have difficulties explaining these benefits because you first
need to argue why you want reflected properties all over the place. And
once that is established (assuming it is), why you would need dedicated
syntax for it.
If reflected properties is a big thing, I'm sure "IDE support" is as easy
to implement with or without this new syntax.
Introducing new syntax must be done with extreme care, and so far this case
looks quite far from convincing.
On Wed, May 1, 2013 at 2:35 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
to convince anyone they need anything they don't understand - I think the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop =
^$user->name;So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to refactor? To
me they really look equivalent from a refactoring point of view.In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal
PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch
--
Etienne Kneuss
http://www.colder.ch
I have to agree with Etienne. Your idea is good, but it is probably better to implement a better Refactoring support in the IDE rather than enable it through the language itself. Dynamically typed languages will always struggle with automatizing refactoring functionalities to a certain extend.
-----Ursprüngliche Nachricht-----
Von: ekneuss@gmail.com [mailto:ekneuss@gmail.com] Im Auftrag von Etienne Kneuss
Gesendet: Mittwoch, 1. Mai 2013 22:12
An: Rasmus Schultz
Cc: Rasmus Lerdorf; Stas Malyshev; PHP internals
Betreff: Re: [PHP-DEV] property de-referencing
The only reason being that the syntax "^$user->name" is "more static"
thannew PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is not.
Refactoring isn't the only benefit - of course most of the benefits
are going to come from IDE support, but would include things like
inline documentation, auto-complete and warnings/errors based on
static analysis/inspections. I already covered that.
PHP-based code-analysis tools would also be able to do a better job
when checking views etc. - if you're using PHP-based static analysis
tools to check for code-smells etc. there's a good chance you have it
configured to skip your view-template folders...
I am sorry, but I find very hard to believe that a "^" preceeding a property access is going to make things easier for any static analysis, and I have done my share of them.
If you look even at the syntax tree, it is not any harder to track new ReflectionProperty($obj, "property") than it is to track ^$obj->property, and that is a fact. You basically have a string literal instead of a T_STRING.
You might argue that the property name does not need to be a string literal, but then what about ^$foo->$bar or ^$foo->{'asd'}? would that be forbidden?
To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working
with a large codebase, and it's error-prone, and therefore requires
manual review of every change before you apply, even for things that
should be quick/simple like renaming a property.
Refactoring in PHP will always be guesswork, error-prone, and will require manual inspection, whether you have a fancy syntax to create ReflectionProperies or not. Types are hard to track statically and that won't change with this. And really, the strict translation of ^$obj->foo is just as easy (and fast) to track by analyses.
In any case, as many already pointed out, this sounds like a lot of
painfor really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?
Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write
simpler, stronger abstractions that provide more comfort and safety in an IDE.
I believe you have difficulties explaining these benefits because you first need to argue why you want reflected properties all over the place. And once that is established (assuming it is), why you would need dedicated syntax for it.
If reflected properties is a big thing, I'm sure "IDE support" is as easy to implement with or without this new syntax.
Introducing new syntax must be done with extreme care, and so far this case looks quite far from convincing.
On Wed, May 1, 2013 at 2:35 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
This is a fringe feature, as evidenced by the fact that you are
having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's
hard to convince anyone they need anything they don't understand - I
think the barrier here is me having difficulty explaining a new
idea/concept. That doesn't make it a fringe feature - I have already
demonstrated by example how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor
to transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop =
^$user->name;So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to
refactor? To me they really look equivalent from a refactoring point of view.In any case, as many already pointed out, this sounds like a lot of
pain for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any
normal PHP code.And the PropertyReference class could be implemented in plain PHP
like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192b
d3db84ddaf84c83Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd
8e73ff80717f3cbNote that the dynamic User::$name property in this example is
properly documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact
that you are having a hard time convincing people that it is
needed, and thus shouldn't overload an existing operator. Visually
it would be confusing to take any well-known operator and give it
a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't
carry this information with them so a lot of things would have to
change internally for this to ever work and if a clean
implementation could be found, like I said, adding it to the
reflection functions is the proper place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch
--
Etienne Kneuss
http://www.colder.ch
PhpStorm has the finest refactoring support you can achieve with the
limited amount of static information in PHP source-code, plus hopefully a
whole bunch of @var and @property annotations. With the amount of
information inherent in PHP source-code, plus the volunteer information
provided by annotations, it still has to do a lot of guess-work, and you
still have to look over the proposed changes and manually correct what it
gets wrong.
I really see annotations in doc-blocks as a symptom of the lack of static
information in the language - the interpreter doesn't need information like
property-types or argument-types, but as it turns out, people do, so we
have to decorate the language with annotations to provide enough
information for people to comprehend the code.
But that means the annotations can now be out of sync with reality -
argument-types and property-types change. We discover, there was a useful
need for this information after all: type checking. So we introduce static
type-hints. The static information wasn't just useful to humans after all.
As for property-types and loads of other things, we annotate everything, in
part because the annotations are useful to people, in part to facilitate
proper IDE support and other forms of machine-analysis. Property type-hints
may not be necessary to run the language, but they are necessary for people
and external static analysis.
PHP is not a machine-friendly language - like most high-level languages, it
was designed with people in mind, which is natural, because people are the
ones who use programming languages. The machines would be satisfied with
machine instructions, if you could memorize them all and keep track of that
in your head.
To write a simple web-application, I'm betting you would need a QUADRILLION
annotations to do that.
Better to take all that static information and make it available to the
machine, so that we can not only have languages people can read, write and
understand - but exploit that rich static information to check that your
code actually does what you say it does.
Isn't that the reason languages evolved?
Why are we always so concerned about what the language is doing, and so
careless with expressiveness and information that makes it meaningful to
human beings?
Dynamically typed languages will always struggle with automatizing
refactoring functionalities to a certain extend
PHP was a dynamically typed language - it is currently a mixed type
language. You have optional static references to types in argument-lists -
even if those are only checked dynamically by the interpreter, they are
usually checked statically by every external tool.
Every well-written application, library, framework etc treats PHP as a
mixed-typed language most of the time, decorating the language up, down and
center with static type-information, everywhere, all the time.
Don't you think that's a symptom of something?
I have to agree with Etienne. Your idea is good, but it is probably better
to implement a better Refactoring support in the IDE rather than enable it
through the language itself. Dynamically typed languages will always
struggle with automatizing refactoring functionalities to a certain extend.-----Ursprüngliche Nachricht-----
Von: ekneuss@gmail.com [mailto:ekneuss@gmail.com] Im Auftrag von Etienne
Kneuss
Gesendet: Mittwoch, 1. Mai 2013 22:12
An: Rasmus Schultz
Cc: Rasmus Lerdorf; Stas Malyshev; PHP internals
Betreff: Re: [PHP-DEV] property de-referencingThe only reason being that the syntax "^$user->name" is "more static"
thannew PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is
not.Refactoring isn't the only benefit - of course most of the benefits
are going to come from IDE support, but would include things like
inline documentation, auto-complete and warnings/errors based on
static analysis/inspections. I already covered that.PHP-based code-analysis tools would also be able to do a better job
when checking views etc. - if you're using PHP-based static analysis
tools to check for code-smells etc. there's a good chance you have it
configured to skip your view-template folders...I am sorry, but I find very hard to believe that a "^" preceeding a
property access is going to make things easier for any static analysis, and
I have done my share of them.If you look even at the syntax tree, it is not any harder to track new
ReflectionProperty($obj, "property") than it is to track ^$obj->property,
and that is a fact. You basically have a string literal instead of a
T_STRING.
You might argue that the property name does not need to be a string
literal, but then what about ^$foo->$bar or ^$foo->{'asd'}? would that be
forbidden?To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working
with a large codebase, and it's error-prone, and therefore requires
manual review of every change before you apply, even for things that
should be quick/simple like renaming a property.Refactoring in PHP will always be guesswork, error-prone, and will require
manual inspection, whether you have a fancy syntax to create
ReflectionProperies or not. Types are hard to track statically and that
won't change with this. And really, the strict translation of ^$obj->foo is
just as easy (and fast) to track by analyses.In any case, as many already pointed out, this sounds like a lot of
painfor really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write
simpler, stronger abstractions that provide more comfort and safety in
an IDE.I believe you have difficulties explaining these benefits because you
first need to argue why you want reflected properties all over the place.
And once that is established (assuming it is), why you would need dedicated
syntax for it.If reflected properties is a big thing, I'm sure "IDE support" is as easy
to implement with or without this new syntax.Introducing new syntax must be done with extreme care, and so far this
case looks quite far from convincing.On Wed, May 1, 2013 at 2:35 PM, Rasmus Schultz <rasmus@mindplay.dk
wrote:This is a fringe feature, as evidenced by the fact that you are
having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's
hard to convince anyone they need anything they don't understand - I
think the barrier here is me having difficulty explaining a new
idea/concept. That doesn't make it a fringe feature - I have already
demonstrated by example how this would be useful in practically every
mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor
to transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop =
^$user->name;So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to
refactor? To me they really look equivalent from a refactoring point of
view.In any case, as many already pointed out, this sounds like a lot of
pain for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any
normal PHP code.And the PropertyReference class could be implemented in plain PHP
like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192b
d3db84ddaf84c83Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd
8e73ff80717f3cbNote that the dynamic User::$name property in this example is
properly documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact
that you are having a hard time convincing people that it is
needed, and thus shouldn't overload an existing operator. Visually
it would be confusing to take any well-known operator and give it
a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't
carry this information with them so a lot of things would have to
change internally for this to ever work and if a clean
implementation could be found, like I said, adding it to the
reflection functions is the proper place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch--
Etienne Kneuss
http://www.colder.ch
I believe you have difficulties explaining these benefits because you
first need to argue why you want reflected properties all over the place.
And once that is established (assuming it is), why you would need dedicated
syntax for it.
I thought that's what I had been doing? Apparently I've just been writing
up long e-mails about nothing.
I don't understand your line of argumentation at all - strings are fine and
literal references to properties refactor just as well?
Okay.
Let's go ahead and quit using the new-statement then, because we don't
really need literal references to class-names - we can just do this instead:
function create($class_name)
{
return new $class_name;
}
$user = create('User');
$user->name = 'xyz';
See how far you'll get with static analysis when you don't even know the
class of an object anymore. Solong to any kind of static analysis whatsover.
Let's get rid of the instanceof-operator while we're at it, this works just
as well:
if (get_class($user) === 'User') {
// yay!
}
You are correct, we don't technically need literal references to anything.
Forget the whole thing.
I'm going to build every app in Drupal from now on, where everything is a
string or an array or a stdClass - at least then there's consistently no
checkable literals or IDE support for anything.
Awesome.
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is
not.Refactoring isn't the only benefit - of course most of the benefits are
going to come from IDE support, but would include things like inline
documentation, auto-complete and warnings/errors based on static
analysis/inspections. I already covered that.PHP-based code-analysis tools would also be able to do a better job when
checking views etc. - if you're using PHP-based static analysis tools to
check for code-smells etc. there's a good chance you have it configured to
skip your view-template folders...I am sorry, but I find very hard to believe that a "^" preceeding a
property access is going to make things easier for any static analysis, and
I have done my share of them.If you look even at the syntax tree, it is not any harder to track new
ReflectionProperty($obj, "property") than it is to track ^$obj->property,
and that is a fact. You basically have a string literal instead of a
T_STRING.
You might argue that the property name does not need to be a string
literal, but then what about ^$foo->$bar or ^$foo->{'asd'}? would that be
forbidden?To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working with a
large codebase, and it's error-prone, and therefore requires manual review
of every change before you apply, even for things that should be
quick/simple like renaming a property.Refactoring in PHP will always be guesswork, error-prone, and will require
manual inspection, whether you have a fancy syntax to create
ReflectionProperies or not. Types are hard to track statically and that
won't change with this. And really, the strict translation of ^$obj->foo is
just as easy (and fast) to track by analyses.In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write simpler,
stronger abstractions that provide more comfort and safety in an IDE.I believe you have difficulties explaining these benefits because you
first need to argue why you want reflected properties all over the place.
And once that is established (assuming it is), why you would need dedicated
syntax for it.If reflected properties is a big thing, I'm sure "IDE support" is as easy
to implement with or without this new syntax.Introducing new syntax must be done with extreme care, and so far this
case looks quite far from convincing.On Wed, May 1, 2013 at 2:35 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's
hard
to convince anyone they need anything they don't understand - I think
the
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by
example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop =
^$user->name;So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to refactor? To
me they really look equivalent from a refactoring point of view.In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal
PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that
you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be
confusing
to take any well-known operator and give it a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could
be
found, like I said, adding it to the reflection functions is the
proper
place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch--
Etienne Kneuss
http://www.colder.ch
I believe you have difficulties explaining these benefits because you
first need to argue why you want reflected properties all over the place.
And once that is established (assuming it is), why you would need dedicated
syntax for it.I thought that's what I had been doing? Apparently I've just been writing
up long e-mails about nothing.I don't understand your line of argumentation at all - strings are fine
and literal references to properties refactor just as well?Okay.
Let's go ahead and quit using the new-statement then, because we don't
really need literal references to class-names - we can just do this instead:function create($class_name) { return new $class_name; } $user = create('User'); $user->name = 'xyz';
See how far you'll get with static analysis when you don't even know the
class of an object anymore. Solong to any kind of static analysis whatsover.
If this was an idiom in PHP, I'm sure static analyses would be built with
enough interprocedural reasoning to handle that case just fine.
Let's get rid of the instanceof-operator while we're at it, this works
just as well:if (get_class($user) === 'User') { // yay! }
You are correct, we don't technically need literal references to anything.
Forget the whole thing.
I'm going to build every app in Drupal from now on, where everything is a
string or an array or a stdClass - at least then there's consistently no
checkable literals or IDE support for anything.
We have User::class now instead of 'User'. You should use it, it makes it
easy to refactor and stuff.
More seriously:
I'm just saying you are arguing for a new syntax that would allow
something rarely used (IMO) to be, as I see it: easier to analyze or
refactor; that doesn't qualify(IMO, again) as important enough to warrant a
syntax change.
Awesome.
On Wed, May 1, 2013 at 7:13 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to refactor?
Not "more static", it is static - a string-based property-reference is
not.Refactoring isn't the only benefit - of course most of the benefits are
going to come from IDE support, but would include things like inline
documentation, auto-complete and warnings/errors based on static
analysis/inspections. I already covered that.PHP-based code-analysis tools would also be able to do a better job when
checking views etc. - if you're using PHP-based static analysis tools to
check for code-smells etc. there's a good chance you have it configured to
skip your view-template folders...I am sorry, but I find very hard to believe that a "^" preceeding a
property access is going to make things easier for any static analysis, and
I have done my share of them.If you look even at the syntax tree, it is not any harder to track new
ReflectionProperty($obj, "property") than it is to track ^$obj->property,
and that is a fact. You basically have a string literal instead of a
T_STRING.
You might argue that the property name does not need to be a string
literal, but then what about ^$foo->$bar or ^$foo->{'asd'}? would that be
forbidden?To me they really look equivalent from a refactoring point of view.
They are not.
Refactoring based on strings is guesswork - it's slow when working with
a large codebase, and it's error-prone, and therefore requires manual
review of every change before you apply, even for things that should be
quick/simple like renaming a property.Refactoring in PHP will always be guesswork, error-prone, and will
require manual inspection, whether you have a fancy syntax to create
ReflectionProperies or not. Types are hard to track statically and that
won't change with this. And really, the strict translation of ^$obj->foo is
just as easy (and fast) to track by analyses.In any case, as many already pointed out, this sounds like a lot of pain
for really little (if any) gain.
Going to take a wild guess and say your IDE or text-editor does not do
static analysis?Yes, there is little immediate gain from the feature itself - but as
demonstrated, valuable long-term gain from being able to write simpler,
stronger abstractions that provide more comfort and safety in an IDE.I believe you have difficulties explaining these benefits because you
first need to argue why you want reflected properties all over the place.
And once that is established (assuming it is), why you would need dedicated
syntax for it.If reflected properties is a big thing, I'm sure "IDE support" is as easy
to implement with or without this new syntax.Introducing new syntax must be done with extreme care, and so far this
case looks quite far from convincing.On Wed, May 1, 2013 at 2:35 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's
hard
to convince anyone they need anything they don't understand - I think
the
barrier here is me having difficulty explaining a new idea/concept.
That
doesn't make it a fringe feature - I have already demonstrated by
example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop =
^$user->name;So basically you want to introduce syntactic sugar for:
new PropertyReference($user, 'name')
The only reason being that the syntax "^$user->name" is "more static"
than new PropertyReference($user, 'name'), and thus easier to refactor? To
me they really look equivalent from a refactoring point of view.In any case, as many already pointed out, this sounds like a lot of
pain for really little (if any) gain.var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any
normal PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that
you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be
confusing
to take any well-known operator and give it a different obscure
meaning.
But yes, syntax-wise ^ could be made to work, the implementation
problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could
be
found, like I said, adding it to the reflection functions is the
proper
place.-Rasmus
--
Etienne Kneuss
http://www.colder.ch--
Etienne Kneuss
http://www.colder.ch
--
Etienne Kneuss
http://www.colder.ch
This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is neededAs with anything that isn't already established and well-known, it's hard
This is like building something and then going out to find a problem that
it will hopefully solve.
to convince anyone they need anything they don't understand - I think the
Perhaps the reason you're having trouble convincing anyone that they need
it is simply because they don't need it? Things I need that solve real
world problems for me are pretty obvious to me. I'm sure the solution
wasn't always obvious but the problem definitely was.
barrier here is me having difficulty explaining a new idea/concept. That
doesn't make it a fringe feature - I have already demonstrated by example
how this would be useful in practically every mainstream framework.Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever workI'm not sure what information you're referring to?
Let's say for the sake of argument, I'm going to use a pre-processor to
transform the following code:$prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
The pre-processor output might look like this:
$nameprop = new PropertyReference($user, 'name'); // $prop = ^$user->name;
var_dump($nameprop->getValue()); // => 'Rasmus'
$nameprop->setValue('Bob');
var_dump($nameprop->getValue()); // => 'Bob'
Only the first line changes - the rest behaves and runs like any normal
PHP
code.And the PropertyReference class could be implemented in plain PHP like
this:class PropertyReference
{
private $_object;private $_propertyName; public function __construct($object, $propertyName) { $this->_object = $object; $this->_propertyName = $propertyName; } public function getObject() { return $this->_object; } public function getPropertyName() { return $this->_propertyName; } public function getValue() { return $this->_object->{$this->_propertyName}; } public function setValue($value) { $this->_object->{$this->_propertyName} = $value; } // and maybe: public function getReflection() { return new ReflectionObject($this->_object); }
}
You can see the above example running in a sandbox here:
http://sandbox.onlinephpfunctions.com/code/87c57301e0f6babb51026192bd3db84ddaf84c83
Someone said they didn't think this would work for accessors, so I'm
including a running sample with a User model that uses accessors:
http://sandbox.onlinephpfunctions.com/code/f2922b3a5dc0e12bf1e6fcacd8e73ff80717f3cb
Note that the dynamic User::$name property in this example is properly
documented and will reflect in an IDE.On Tue, Apr 30, 2013 at 8:43 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:If the asterisk (or some other character) offers and easier
implementation path, whatever.It doesn't. This is a fringe feature, as evidenced by the fact that you
are having a hard time convincing people that it is needed, and thus
shouldn't overload an existing operator. Visually it would be confusing
to take any well-known operator and give it a different obscure meaning.
But yes, syntax-wise ^ could be made to work, the implementation problem
I referred to is lower-level than that. Properties simply don't carry
this information with them so a lot of things would have to change
internally for this to ever work and if a clean implementation could be
found, like I said, adding it to the reflection functions is the proper
place.-Rasmus
Hi Rasmus,
I agree with you that strings are not the best way to refer to an element
sometimes. However, to me your Symfony2 example only demonstrates the flaw
of the component's design decision, not the limitation of the language.
Sometimes developers (not just Symfony, but other frameworks too) don't
hesitate to use contextless strings to refer to meta-data, because they
underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.
Regards,
Seva
Any PHP dev who works with a mainstream framework does this daily, but the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except of
course that, no, they're not - they're obviously just strings... rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP for a
living) use form abstractions and object/relational-mappers of some sort,
so this has practical applications for practically everyone, everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object property
the object property itself, not it's value:
You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.
I don't think the Symfony component could have done a much better job under
the circumstances, at least not without the sacrifice of readable code -
typing out new PropertyReference($object, 'User::$name') sure would be
clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.
I think this is a good example of those times when PHP developers tend to
look far, far away from Java - as far away as possible - for solutions that
are elegant and a good fit for PHP.
new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.
As opposed to ^$user->name which contains the minimum amount of required
information - the object and property-name, nothing else.
Hi Rasmus,
I agree with you that strings are not the best way to refer to an element
sometimes. However, to me your Symfony2 example only demonstrates the flaw
of the component's design decision, not the limitation of the language.
Sometimes developers (not just Symfony, but other frameworks too) don't
hesitate to use contextless strings to refer to meta-data, because they
underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily, but the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except of
course that, no, they're not - they're obviously just strings... rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and introduce
a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP for a
living) use form abstractions and object/relational-mappers of some sort,
so this has practical applications for practically everyone, everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Not elegant - true, not expressive - I don't agree.
My reference to Java was not to point how things should be, but how people
find proper ways to overcome missing edge features of a language.
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend to
look far, far away from Java - as far away as possible - for solutions that
are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of required
information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an element
sometimes. However, to me your Symfony2 example only demonstrates the flaw
of the component's design decision, not the limitation of the language.
Sometimes developers (not just Symfony, but other frameworks too) don't
hesitate to use contextless strings to refer to meta-data, because they
underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily, but
the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support
and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP for a
living) use form abstractions and object/relational-mappers of some sort,
so this has practical applications for practically everyone, everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
BTW, I didn't propose to wrap any use of a property reference into a meta
object, in this case a certain distinguishable string format could
represent it with no extra handling.
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend to
look far, far away from Java - as far away as possible - for solutions that
are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of required
information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an element
sometimes. However, to me your Symfony2 example only demonstrates the flaw
of the component's design decision, not the limitation of the language.
Sometimes developers (not just Symfony, but other frameworks too) don't
hesitate to use contextless strings to refer to meta-data, because they
underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily, but
the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support
and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP for a
living) use form abstractions and object/relational-mappers of some sort,
so this has practical applications for practically everyone, everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Well, I don't disagree as such - there's any number of (mostly bad) ways to
work around missing language features...
BTW, I didn't propose to wrap any use of a property reference into a meta
object, in this case a certain distinguishable string format could
represent it with no extra handling.On Mon, May 6, 2013 at 12:44 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend to
look far, far away from Java - as far away as possible - for solutions that
are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of required
information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an
element sometimes. However, to me your Symfony2 example only demonstrates
the flaw of the component's design decision, not the limitation of the
language. Sometimes developers (not just Symfony, but other frameworks too)
don't hesitate to use contextless strings to refer to meta-data, because
they underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily, but
the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except
of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic
refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support
and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but
use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP for
a
living) use form abstractions and object/relational-mappers of some
sort,
so this has practical applications for practically everyone, everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language? It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Good developers research and find best ways to use the available tools
before inventing new ones.
Well, I don't disagree as such - there's any number of (mostly bad) ways
to work around missing language features...BTW, I didn't propose to wrap any use of a property reference into a meta
object, in this case a certain distinguishable string format could
represent it with no extra handling.On Mon, May 6, 2013 at 12:44 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend
to look far, far away from Java - as far away as possible - for solutions
that are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of required
information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an
element sometimes. However, to me your Symfony2 example only demonstrates
the flaw of the component's design decision, not the limitation of the
language. Sometimes developers (not just Symfony, but other frameworks too)
don't hesitate to use contextless strings to refer to meta-data, because
they underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily, but
the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references - except
of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can be
proofed using static analysis, which also means better IDE support with
property auto-completion, inline documentation, and automatic
refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE support
and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but
use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP
for a
living) use form abstractions and object/relational-mappers of some
sort,
so this has practical applications for practically everyone,
everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for the
sake
of discussion only - if it's more practical to use another character
for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com
wrote:
Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language?
It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
And what do good developers do when the best ways have long since been
identified - and the limitations of the language prevents them from
implementing any new ideas?
I have hundreds of PHP experiments collected in a sandbox over the years -
a good way to build and handle web-forms is one of the last things I have
not found a satisfying solution to, and I am not happy with what anybody
else has come up with either. At some point, it's natural to start asking
why, comparing to other languages, etc. - short of inventing DSLs, I have
not seen much that really impresses me.
I don't know, maybe I should just let that one go and accept that it's
always going to be crap. Maybe the problem in the first place is trying to
drive the client-side from the server-side, and maybe client-side
frameworks is the right way to go - put the UI abstraction in the UI rather
than on the server. We'll always need a few web-forms, I think, but maybe
it's time to stop struggling for better server-side form handling and start
moving towards fully client-side UI...
(sorry if I'm going off on a tangent here - just sharing some of the
thoughts that lead me down this path to begin with...)
Good developers research and find best ways to use the available tools
before inventing new ones.Well, I don't disagree as such - there's any number of (mostly bad) ways
to work around missing language features...On Mon, May 6, 2013 at 1:12 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
BTW, I didn't propose to wrap any use of a property reference into a
meta object, in this case a certain distinguishable string format could
represent it with no extra handling.On Mon, May 6, 2013 at 12:44 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend
to look far, far away from Java - as far away as possible - for solutions
that are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of
required information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an
element sometimes. However, to me your Symfony2 example only demonstrates
the flaw of the component's design decision, not the limitation of the
language. Sometimes developers (not just Symfony, but other frameworks too)
don't hesitate to use contextless strings to refer to meta-data, because
they underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily,
but the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references -
except of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can
be
proofed using static analysis, which also means better IDE support
with
property auto-completion, inline documentation, and automatic
refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE
support and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course, but
use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP
for a
living) use form abstractions and object/relational-mappers of some
sort,
so this has practical applications for practically everyone,
everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to this
discussion. And as I explained earlier, the ^ operator is used for
the sake
of discussion only - if it's more practical to use another character
for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <
smalyshev@sugarcrm.com>wrote:Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy to
write a class that does that, but why it should be in the language?
It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Maybe PHP is just not for you. There are other languages in the sea :)
And what do good developers do when the best ways have long since been
identified - and the limitations of the language prevents them from
implementing any new ideas?I have hundreds of PHP experiments collected in a sandbox over the years -
a good way to build and handle web-forms is one of the last things I have
not found a satisfying solution to, and I am not happy with what anybody
else has come up with either. At some point, it's natural to start asking
why, comparing to other languages, etc. - short of inventing DSLs, I have
not seen much that really impresses me.I don't know, maybe I should just let that one go and accept that it's
always going to be crap. Maybe the problem in the first place is trying to
drive the client-side from the server-side, and maybe client-side
frameworks is the right way to go - put the UI abstraction in the UI rather
than on the server. We'll always need a few web-forms, I think, but maybe
it's time to stop struggling for better server-side form handling and start
moving towards fully client-side UI...(sorry if I'm going off on a tangent here - just sharing some of the
thoughts that lead me down this path to begin with...)Good developers research and find best ways to use the available tools
before inventing new ones.On Mon, May 6, 2013 at 2:46 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Well, I don't disagree as such - there's any number of (mostly bad) ways
to work around missing language features...On Mon, May 6, 2013 at 1:12 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
BTW, I didn't propose to wrap any use of a property reference into a
meta object, in this case a certain distinguishable string format could
represent it with no extra handling.On Mon, May 6, 2013 at 12:44 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers tend
to look far, far away from Java - as far away as possible - for solutions
that are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of
required information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an
element sometimes. However, to me your Symfony2 example only demonstrates
the flaw of the component's design decision, not the limitation of the
language. Sometimes developers (not just Symfony, but other frameworks too)
don't hesitate to use contextless strings to refer to meta-data, because
they underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily,
but the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references -
except of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase can
be
proofed using static analysis, which also means better IDE support
with
property auto-completion, inline documentation, and automatic
refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE
support and
static analysis for textInput() and dateInput() which were previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course,
but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP
for a
living) use form abstractions and object/relational-mappers of some
sort,
so this has practical applications for practically everyone,
everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to
this
discussion. And as I explained earlier, the ^ operator is used for
the sake
of discussion only - if it's more practical to use another character
for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <
smalyshev@sugarcrm.com>wrote:Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy
to
write a class that does that, but why it should be in the
language? It
certainly doesn't look like something sizeable portion of PHP devs
would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
I have tried tons of other languages, actively watching at least a few
others in the hopes they'll mature - but I keep coming back to PHP for some
reason.
It's an abusive relationship. Maybe I should seek counseling ;-)
Maybe PHP is just not for you. There are other languages in the sea :)
On Tue, May 7, 2013 at 10:32 AM, Rasmus Schultz rasmus@mindplay.dkwrote:
And what do good developers do when the best ways have long since been
identified - and the limitations of the language prevents them from
implementing any new ideas?I have hundreds of PHP experiments collected in a sandbox over the years
- a good way to build and handle web-forms is one of the last things I have
not found a satisfying solution to, and I am not happy with what anybody
else has come up with either. At some point, it's natural to start asking
why, comparing to other languages, etc. - short of inventing DSLs, I have
not seen much that really impresses me.I don't know, maybe I should just let that one go and accept that it's
always going to be crap. Maybe the problem in the first place is trying to
drive the client-side from the server-side, and maybe client-side
frameworks is the right way to go - put the UI abstraction in the UI rather
than on the server. We'll always need a few web-forms, I think, but maybe
it's time to stop struggling for better server-side form handling and start
moving towards fully client-side UI...(sorry if I'm going off on a tangent here - just sharing some of the
thoughts that lead me down this path to begin with...)On Tue, May 7, 2013 at 9:41 AM, Seva Lapsha seva.lapsha@gmail.comwrote:
Good developers research and find best ways to use the available tools
before inventing new ones.On Mon, May 6, 2013 at 2:46 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Well, I don't disagree as such - there's any number of (mostly bad)
ways to work around missing language features...On Mon, May 6, 2013 at 1:12 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
BTW, I didn't propose to wrap any use of a property reference into a
meta object, in this case a certain distinguishable string format could
represent it with no extra handling.On Mon, May 6, 2013 at 12:44 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Seva,
I understand that you can reference properties more consistently
using "{fullClassName}::{fieldName}" notation, but it's still a string, and
although it's now almost practically safe to assume that strings formatted
in that way are property-references, it still doesn't address the problem
in a way that is elegant or expressive.I don't think the Symfony component could have done a much better job
under the circumstances, at least not without the sacrifice of readable
code - typing out new PropertyReference($object, 'User::$name') sure would
be clunky, and not even really safe, since you can't guarantee that the
class-name of $object is known, and in every property-reference, the User
class-reference is now embedded statically in every property-reference, in
the form of a string.I think this is a good example of those times when PHP developers
tend to look far, far away from Java - as far away as possible - for
solutions that are elegant and a good fit for PHP.new PropertyReference($object, 'User::$name') contains two static
references too many, to both PropertyReference and User.As opposed to ^$user->name which contains the minimum amount of
required information - the object and property-name, nothing else.On Mon, May 6, 2013 at 12:08 PM, Seva Lapsha seva.lapsha@gmail.comwrote:
Hi Rasmus,
I agree with you that strings are not the best way to refer to an
element sometimes. However, to me your Symfony2 example only demonstrates
the flaw of the component's design decision, not the limitation of the
language. Sometimes developers (not just Symfony, but other frameworks too)
don't hesitate to use contextless strings to refer to meta-data, because
they underestimate the importance of keeping static referability of static
entities. If they would use conventional full notation of references, e.g.
"{fullClassName}::{fieldName}" in a string, this would solve your initial
problem (and allow static analyzers which could be aware of the context of
the framework to do their job). This is how these kind of dilemmas are
solved in the world of Java for instance, where property references don't
exist too.Regards,
SevaOn Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz rasmus@mindplay.dkwrote:
Any PHP dev who works with a mainstream framework does this daily,
but the
frameworks rely on strings for property-names.Take this example from the Symfony manual, for example:
class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; } } $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm();
In this example, 'task' and 'dueDate' are property-references -
except of
course that, no, they're not - they're obviously just strings...
rewriting
this example to use a (fictive) form builder API with static
property-references:$form = $this->createFormBuilder() ->add(^$task->task, 'text') ->add(^$task->dueDate, 'date') ->getForm();
We now have static property-references, which means the codebase
can be
proofed using static analysis, which also means better IDE support
with
property auto-completion, inline documentation, and automatic
refactoring
for operations like renaming properties, etc.Note that $task need not be passed to createFormBuilder() anymore -
instead, we can now use PropertyReference::getObject() inside the
form-builder to obtain the instance.For that matter, we can now scrap the form-builder entirely and
introduce a
simple form-helper in the view instead:Task name: <?= $form->textInput(^$task->task) ?> Due Date: <?= $form->dateInput(^$task->dueDate) ?>
This is even better, because we now have the same level of IDE
support and
static analysis for textInput() and dateInput() which were
previously
unchecked strings.Or even simpler:
Task name: <?= $form->input(^$task->task) ?> Due Date: <?= $form->input(^$task->dueDate) ?>
Using PropertyReference::getObject() and reflection inside the
form-helper's input() method, we can now use property-annotations to
specify the input-type. This is a matter of preference of course,
but use
of annotations in Symfony is pretty popular.This is just one example - most PHP devs (at least those who do PHP
for a
living) use form abstractions and object/relational-mappers of some
sort,
so this has practical applications for practically everyone,
everywhere.Rasmus Lerdorf wrote:
It is certainly not worth overloading the XOR operator for
Are we really going to quibble about syntax? This adds nothing to
this
discussion. And as I explained earlier, the ^ operator is used for
the sake
of discussion only - if it's more practical to use another
character for
this operator, I don't care what it looks like.On Tue, Apr 30, 2013 at 4:58 PM, Stas Malyshev <
smalyshev@sugarcrm.com>wrote:Hi!
I'm proposing we need a way to statically reference an object
property -
the object property itself, not it's value:You probably have use case for that, and it should be pretty easy
to
write a class that does that, but why it should be in the
language? It
certainly doesn't look like something sizeable portion of PHP
devs would
do frequently.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227