I am really surprised that there is so few people interested in such a feature. IMO, it's an amazing idea, not just for forms, and not just for properties.

Here is a quick list of use cases where one would use "meta" on its code:

- Forms generation (examples have already been given)
- ORM mapping (Doctrine for example)
- DTO mapping (mapping some objects to other objects/data structures)
- Dependency Injection configuration (defining dependencies)
- Routing (mapping routes to controller class methods)
- AOP
- …

Another example: the PropertyAccess component of Symfony (http://symfony.com/blog/new-in-symfony-2-2-new-propertyaccess-component).

Here is what we can use today for doing some "meta":

- string references (PHP strings, XML, YAML…)
- annotations

If you have worked with ZF, Symfony, Doctrine, … you know that working with strings make refactoring, code completion and static analysis very difficult!

In modern frameworks, there are more and more annotations and config files, and that's a sign IMO: that's a sign that we do a lot of meta. And having a language feature for doing that (as an alternative, not a replacement for current solutions) would be amazing.

Here are some examples with some random syntax (probably problematic but that's not the point) to illustrate:

// Property
$propertyReference = ^$article->name; // returns a PropertyReference
$propertyReflection = ^My\Article::name // returns a ReflectionProperty

// Method
$methodReference = ^$article->getName(); // returns a MethodReference
$methodReflection = ^My\Article::getName(); // returns a ReflectionMethod

// Form generation
$form->addInput(^$article->name);

// ORM mapping
$class->mapField(^Article::name, 'string');

// DTO mapping
$mapper->map(^$article->name, ^ArticleDTO::label);

// DI configuration
$container->bind(^My\ServiceInterface)
    ->to(^My\Service)
    ->withSetter(^My\Service::setFoo(), ^My\Foo);

// Routing
$app->get('/hello/{name}', ^$myController->helloAction());

// AOP
$aop->beforeMethod(^$myObject->someMethod(), function() {
    echo "Hello World!";
});



In all those examples, you can refactor your code, find usages of properties, traverse call hierarchy, have 100% code completion, have better code analysis…

PS: please please don't mind the syntax of the examples, let's keep the discussion on the idea for now.


Le 07/05/2013 16:32, Rasmus Schultz a écrit :
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.lap...@gmail.com> wrote:

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 <ras...@mindplay.dk> wrote:

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.lap...@gmail.com>wrote:

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 <ras...@mindplay.dk>wrote:

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.lap...@gmail.com>wrote:

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


On Tue, Apr 30, 2013 at 6:24 PM, Rasmus Schultz <ras...@mindplay.dk>wrote:

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 <
smalys...@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











--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to