> And if you have numerous getter/setters, it will feel and look like shit indeed -- in any language, no matter how terse the syntax. However, in that case the problem is with program design, not with the language itself.

You missed a core issue of the whole getter/setter/properties business: future-proofing/evolvability.

In Java, people generate bunches of getters/setters because if you ever need to create "virtual" members (add pre/post conditions) with public members you've just broken your interface (it's also used by technologies like Java Beans), you can't evolve gracefully from one to the other, hence Java IDEs having become very good at auto-generating getters and setters (including the type-induced naming variations). Likewise in C#, you can't replace a public member by a property without recompiling all clients (and if you follow the C# naming conventions, properties are PascalCased whereas members are camelCased), hence new syntactic forms having been introduced over time to make "direct proxy" properties easier and easier to create (last time I checked, creating a R/W property called Foo in C# is down to `public $type Foo { get; set; }`, and no field declaration at all as the field is implicitly generated by the property)

And so is it in PHP: if you use public members you can replace them by __get or __set, but if you ever need more than one or two fields you're fucked as you end up with a ball of mud of manual static dispatches. If you go the Java way, you get the Java result.

Now you assert that it's the same in every language. This is patently incorrect, and let me demonstrate it with two languages as far apart on this issue as they could be, Ruby and Python (very similar on most things, but not on this)

* Ruby has no public members. Period, end of the story. In Ruby, a public member is already a property, but because it's common to just expose a member without pre/post conditions it has accelerators for this such as `attr_accessor`. `attr_accessor :foo` creates a read/write property (actually a pair of methods) `foo` on the object which will proxy to the private member `@foo`. This means if it's exposed in Ruby, it's already a property. If you want to add pre/post conditions, remove the `attr_accessor` call and replace it with an explicit pair of `def foo` and `def foo= value`. This evolves gracefully and scales trivially, declaring a property in Ruby is as terse as (if not terser than) declaring a public member in PHP.

* Python goes the other way: everything is public. Period, end of the story. But it also has `property` which is an object implementing the descriptor protocol. Long story short, you can replace a public member `foo` by a property `foo` (created at the class level), and when accessed from the instance they will be indistinguishable. So in Python, just as in Ruby, you can trivially swap out a field for a property as needed without having to dispatch anything manually or defensively pre-generate a bunch of crap.

> Ask your co-workers kindly not to carry over Java thinking into PHP world. Really, each language performs best when used in its default way.

Getters and setters is the default PHP way. Hell, all of the Zend framework uses getters and setters everywhere[0]. __get and __set (and __call if you really want to talk about that one) are the special cases for dynamic fields and methods (e.g. in ORM), not for static properties.

As to my coworkers, they've switched well away from PHP a long time ago.

> Also, you have __call() in similar vein, which lets you do pretty neat results: http://scriptor.github.com/pharen/index.html

I don't see why you'd need __call to compile Lisp into PHP.

[0] example: the request object http://framework.zend.com/manual/en/zend.controller.request....