# Property Overloading RFC

- Thread: https://externals.io/message/17491
- Original archive: https://news-web.php.net/php.internals/17491
- Started by Derick Rethans on 2005-08-02T13:05:52+00:00
- Messages: 51
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/17491.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #17491 — Derick Rethans — 2005-08-02T13:05:52+00:00

URL: https://externals.io/message/17491#17491

Hello!

we're finding some problems with property overloading (__get() and 
__set()). Here is an RFC describing what we'd like to see changed. 
Please comment on this.


Introduction:
PHP currently supports property overloading with the magic functions __get()
and __set(). Those methods are called when the code "echo $object->a" or
"$object->a = 42" are executed and the property "a" is not declared in the
class. The magic methods are responsibly for:
- checking if the property actually "exists"
- setting the value or returning the value depending on the action

Problems:
1. There is no way to document the 'virtual' properties with any of the existing
   documentation tools (such as phpdoc and doxygen)
2. There is no way how the magic methods know if a specific 'virtual' property
   exists or not as those properties are not declared usually - unless you
   define an array with property names as a class constant (which is not
   allowed either).
3. There is no way for the magic methods to return a meaningfull error when a
   property doesn't "exist". Of course it is possible to throw an error with
   "trigger_error" or "throw" in case a property doesn't "exist" in a specific
   class, but the file and line numbers would not match the actually get/set
   action. `debug_backtrace()` can be used to retrieve the correct file and line,
   but as you have to do this for every class where you want to use setters and
   getters *and* you have to implement your own error message rendering
   function this is not really a suitable option either.


Solutions:
- For problem 1. we can introduce a keyword (or use an existing one) to define
  that it is a virtual property ('abstract' or 'virtual' come to mind). When
  declaring it like this it's easy to document, and we can also implement
  visibility for those virtual properties.  Marcus already has a patch for
  this somewhere, which uses the "abstract" keyword for this purpose:

<?php
class Base
{
	/**
	 * @var int   Contains all X
	 */
	abstract public $x = 1;
	
	/**
	 * @var int   Contains all Y
	 */
	abstract protected $y = 2;

	//  abstract private $z = 3; abstract properties cannot be private
}
?>

- In combination to the introduced keyword we need an easy way to check if a
  passed property name is declared in the class as 'virtual'. Currently (with
  the 'abstract' keyword properly implemented) you'd have to do:

<?php
class Base
{
	abstract public $x = 1;
	
	function __get($name)
	{
		try {
			$prop = new ReflectionProperty('Base', $name);
			if ( !$prop->isAbstract() ) {
				/* throw error */
			}
		} catch ($e) {
			/* throw error */
		}
	}
}

$b = new Base();
echo $b->foo;
?>

  This is ofcourse overly complicated. A better workable solution would be -
  without breaking BC (suggestions for syntax here are very welcome):

<?php
class Base
{
	abstract public $x = 1;
	
	function __get($name)
	{
		if (!self::isVirtual($name))) {
			/* throw error */
		}
	}
}

$b = new Base();
echo $b->foo;
?>

- Problem 3 can be solved by:
  * allowing optional by-ref parameters to the __set
    and __get function, so that their signatures become:

    function __set($name, $value [, &$error] )
    function __get($name [, &$error] )

	If the parameter is not given things behave just like they do now -> __set
	and __get can not throw meaningful errors with the correct file/line of the
	conflicting statement

	If the parameter is used in the function's declaration and is set to
	"false" when the __set or __get function returns, the engine can throw an
	error on the assignment line with the correct file/line combination. If
	it's set to "true" (or "null") then the engine should not throw any error.

  * Use a different __set and __get function for 'abstract' properties, then
    the engine can already determine if you're doing something wrong before
    executing the __set and __get methods.


regards,
Derick

-- 
Derick Rethans
http://derickrethans.nl | http://ez.no | http://xdebug.org

---

## #17493 — ondrej@kmit.sk — 2005-08-02T14:05:30+00:00

URL: https://externals.io/message/17491#17493 · In reply to: #17491

Derick Rethans wrote:
> Hello!
> 
> we're finding some problems with property overloading (__get() and 
> __set()). Here is an RFC describing what we'd like to see changed. 
> Please comment on this.
> 
> 
> Introduction:
> PHP currently supports property overloading with the magic functions __get()
> and __set(). Those methods are called when the code "echo $object->a" or
> "$object->a = 42" are executed and the property "a" is not declared in the
> class. The magic methods are responsibly for:
> - checking if the property actually "exists"
> - setting the value or returning the value depending on the action
> 
> Problems:
> 1. There is no way to document the 'virtual' properties with any of the existing
>    documentation tools (such as phpdoc and doxygen)
> 2. There is no way how the magic methods know if a specific 'virtual' property
>    exists or not as those properties are not declared usually - unless you
>    define an array with property names as a class constant (which is not
>    allowed either).
> 3. There is no way for the magic methods to return a meaningfull error when a
>    property doesn't "exist". Of course it is possible to throw an error with
>    "trigger_error" or "throw" in case a property doesn't "exist" in a specific
>    class, but the file and line numbers would not match the actually get/set
>    action. `debug_backtrace()` can be used to retrieve the correct file and line,
>    but as you have to do this for every class where you want to use setters and
>    getters *and* you have to implement your own error message rendering
>    function this is not really a suitable option either.

what about:

<?php

class GetSet0 {
	function __get($name) {}
	function __set($name, $value) {}
}

class GetSet1 {
	property $x;
	// or virtual $x, ...

}

class GetSet2 {
	property $x { __get, __set }

	function __get($name) {}
	function __set($name, $value) {}

}

class GetSet3 {
	property $x { getMethod, setMethod }

	function getMethod() {}
	function setMethod($value]) {}

}

?>

Features:
1) Easy way to document properties
2) No BC break with code relies on __get, __set

Clases GetSet0, GetSet1 and GetSet2 are equivalent and third class 
GetSet3 use different methods to handle $x property;

There is a nice way to declare reaonly properties

property $x { getMethod }

or

property $x { getMethod, null }

and writeonly propeties :)

property $x { null, setMethod }

If someone touch undeclared property and class don't have __get/__set 
Zend engine can raise exception ... It's good way? I don't know.

-- 
Ondrej Ivanic
(ondrej@kmit.sk)

---

## #17503 — Christian Schneider — 2005-08-02T19:07:59+00:00

URL: https://externals.io/message/17491#17503 · In reply to: #17491

Derick Rethans wrote:
> class. The magic methods are responsibly for:
> - checking if the property actually "exists"

This is something I wouldn't encourage as one of the virtues of fully 
dynamic languages is the "lack" of checking this. Otherwise what happens 
if e.g. one inherits such a class to extend it? Does it have to know 
about the get/set methods and the necessary declaration of attributes?

And as far as "magic" fields are concerned: IMHO the currently available 
mechanism of checking the property name against a (possibly e.g. from a 
DB dynamically created) array in the object is sufficient.

So personally I'd not add a language feature as it adds complexity with 
little (or arguable) gain.

My $.02,
- Chris

---

## #17506 — James Crumpton — 2005-08-02T21:22:39+00:00

URL: https://externals.io/message/17491#17506 · In reply to: #17491

My concern with the self::isVirtual() syntax would be...

class Base {
     function __get($name) {
         if (!self::isVirtual($name))
             throw;
     }
}

class Foo {
     abstract public $bar = 1;
}

$f = new Foo;
echo $f->bar;

... Are these 'virtual' members going to work like static members, in that using 
self:: in a base class doesn't allow access to those static members of 
inheriting classes? ie, will the above example throw an error or not, like it 
would if a similar thing with statics were to try and be done.

Derick Rethans wrote:

 >   This is ofcourse overly complicated. A better workable solution would be -
 >   without breaking BC (suggestions for syntax here are very welcome):
 >
 > <?php
 > class Base
 > {
 >     abstract public $x = 1;
 >
 >     function __get($name)
 >     {
 >         if (!self::isVirtual($name))) {
 >             /* throw error */
 >         }
 >     }
 > }
 >
 > $b = new Base();
 > echo $b->foo;
 > ?

---

## #17507 — Greg Beaver — 2005-08-03T02:56:26+00:00

URL: https://externals.io/message/17491#17507 · In reply to: #17491

Hi,

As for the first question of how to document virtual properties, I have 
been recommending that users do this textually inside the docblock for 
__get()/__set().  This is actually ideal in almost every case, as anyone 
using __get()/__set() for finite, concrete properties should almost 
definitely be instead using plain old properties.  I wonder if adding 
this language feature might be a bit too hopeful.  For instance, most 
implementations I have seen of __get()/__set() use them because it isn't 
possible to know the names of the variables in advance.  Simplexml and 
ext/soap are great examples of extensions that were they implemented in 
userspace would not be able to use the abstract/virtual keyword proposed 
because until the specific class is instantiated, one can't know what 
they will be working with.  The Savant template engine may use them for 
grabbing filtered variables in the future, another good example of "you 
must document this with prose, not with program syntax".

Having said this, if the proposal continues, I do have some suggestions.

2)

<?php
class Base
{
  	abstract public $x = 1;
  	
  	function __get($name)
  	{
  		if (!$this->isAbstract($name))) {
  			/* throw error */
  		}
  	}
}
?>

or

<?php
class Base
{
  	virtual public $x = 1;
  	
  	function __get($name)
  	{
  		if (!$this->isVirtual($name))) {
  			/* throw error */
  		}
  	}
}
?>

I prefer the 2nd, as it will not confuse with abstract classes (and it 
will definitely confuse users if we start mixing metaphors 
programmatically).

I also prefer $this-> to self:: as it will allow (as James Crumpton 
raised) inheritance without redefinition of __get()/__set().

> 
> - Problem 3 can be solved by:
>   * allowing optional by-ref parameters to the __set
>     and __get function, so that their signatures become:
> 
>     function __set($name, $value [, &$error] )
>     function __get($name [, &$error] )
> 
> 	If the parameter is not given things behave just like they do now -> __set
> 	and __get can not throw meaningful errors with the correct file/line of the
> 	conflicting statement
> 
> 	If the parameter is used in the function's declaration and is set to
> 	"false" when the __set or __get function returns, the engine can throw an
> 	error on the assignment line with the correct file/line combination. If
> 	it's set to "true" (or "null") then the engine should not throw any error.
> 
>   * Use a different __set and __get function for 'abstract' properties, then
>     the engine can already determine if you're doing something wrong before
>     executing the __set and __get methods.

It seems to me the best solution would be to allow error to be set to 
false or an exception object, which would be then thrown as if it was on 
the offending line.  This would allow the user to customize the error 
message as well as the line/file.

Greg

---

## #17511 — Marcus Boerger — 2005-08-03T17:08:42+00:00

URL: https://externals.io/message/17491#17511 · In reply to: #17507

Hello Greg,

Wednesday, August 3, 2005, 4:56:26 AM, you wrote:

> Hi,

> As for the first question of how to document virtual properties, I have 
> been recommending that users do this textually inside the docblock for 
> __get()/__set().  This is actually ideal in almost every case, as anyone 
> using __get()/__set() for finite, concrete properties should almost 
> definitely be instead using plain old properties.  I wonder if adding 
> this language feature might be a bit too hopeful.  For instance, most 
> implementations I have seen of __get()/__set() use them because it isn't 
> possible to know the names of the variables in advance.  Simplexml and 
> ext/soap are great examples of extensions that were they implemented in 
> userspace would not be able to use the abstract/virtual keyword proposed 
> because until the specific class is instantiated, one can't know what 
> they will be working with.  The Savant template engine may use them for 
> grabbing filtered variables in the future, another good example of "you 
> must document this with prose, not with program syntax".

How about lazy initialization? You cannot have a declared property for those
atm.

> Having said this, if the proposal continues, I do have some suggestions.

> 2)

> <?php
> class Base
> {
>         abstract public $x = 1;
  	
>         function __get($name)
>         {
>                 if (!$this->isAbstract($name))) {
>                         /* throw error */
>                 }
>         }
> }
?>>

> or

> <?php
> class Base
> {
>         virtual public $x = 1;
  	
>         function __get($name)
>         {
>                 if (!$this->isVirtual($name))) {
>                         /* throw error */
>                 }
>         }
> }
?>>

> I prefer the 2nd, as it will not confuse with abstract classes (and it 
> will definitely confuse users if we start mixing metaphors 
> programmatically).

You would need to add another keyword for no reason.

> I also prefer $this-> to self:: as it will allow (as James Crumpton 
> raised) inheritance without redefinition of __get()/__set().

I prefer here using property_is_virtual($this, $name).

> > […]

> It seems to me the best solution would be to allow error to be set to 
> false or an exception object, which would be then thrown as if it was on 
> the offending line.  This would allow the user to customize the error 
> message as well as the line/file.

I suggested exceptions but they are not always acceptable and overcomplicate
many things too much and finally come with some danger.

Best regards,
 Marcus

---

## #17520 — Andrei Zmievski — 2005-08-03T23:52:50+00:00

URL: https://externals.io/message/17491#17520 · In reply to: #17491

> Solutions:
> - For problem 1. we can introduce a keyword (or use an existing  
> one) to define
>   that it is a virtual property ('abstract' or 'virtual' come to  
> mind). When
>   declaring it like this it's easy to document, and we can also  
> implement
>   visibility for those virtual properties.  Marcus already has a  
> patch for
>   this somewhere, which uses the "abstract" keyword for this purpose:
>
> <?php
> class Base
> {
>     /**
>      * @var int   Contains all X
>      */
>     abstract public $x = 1;
>
>     /**
>      * @var int   Contains all Y
>      */
>     abstract protected $y = 2;
>
>     //  abstract private $z = 3; abstract properties cannot be private
> }
> ?>

The whole point of these "virtual" properties is that their names can  
be parameterized. If you have 1000 of these variables (in a DB or  
somewhere), how would you declare them as "abstract" or "virtual"?

>   This is ofcourse overly complicated. A better workable solution  
> would be -
>   without breaking BC (suggestions for syntax here are very welcome):
>
> <?php
> class Base
> {
>     abstract public $x = 1;
>
>     function __get($name)
>     {
>         if (!self::isVirtual($name))) {
>             /* throw error */
>         }
>     }
> }
>
> $b = new Base();
> echo $b->foo;
> ?>

How about a __have_prop() method that you can call to find out if a  
certain virtual property exists?

-Andrei

---

## #17521 — Lukas Smith — 2005-08-04T00:02:46+00:00

URL: https://externals.io/message/17491#17521 · In reply to: #17520

I wonder if it wouldnt be enough to be able to force the triggering of 
__set(), __get() for all properties be enough to deal with your situation?

regards,
Lukas

---

## #17523 — Derick Rethans — 2005-08-04T07:09:19+00:00

URL: https://externals.io/message/17491#17523 · In reply to: #17520

> The whole point of these "virtual" properties is that their names can be
> parameterized. If you have 1000 of these variables (in a DB or somewhere), how
> would you declare them as "abstract" or "virtual"?

Then you don't do it - it's not a requirement... just an optional thing 
(and ofcourse you can't do the __have_prop() thing then that you 
suggested below.

> > […]

[snip]

> How about a __have_prop() method that you can call to find out if a certain
> virtual property exists?

Works for me, but it needs to be able to called statically (::) and 
dynamically (->).

Derick

---

## #17524 — Derick Rethans — 2005-08-04T07:10:00+00:00

URL: https://externals.io/message/17491#17524 · In reply to: #17521

> I wonder if it wouldnt be enough to be able to force the triggering of
> __set(), __get() for all properties be enough to deal with your situation?

No, besides that would break BC, it would also not solve the problem of 
returning errors correctly.

Derick

---

## #17528 — Lukas Smith — 2005-08-04T08:22:04+00:00

URL: https://externals.io/message/17491#17528 · In reply to: #17524

Derick Rethans wrote:
> 
> 
> 
> > […]
> 
> 
> No, besides that would break BC, it would also not solve the problem of 
> returning errors correctly.

I said "be able to" and not that this should become the norm.
So you would be able to flag an object to behave in this way. Heck this 
flag could be "allow now virtual properties, and trigger __set()/__get() 
  always and throw the proper error otherwise".

regards,
Lukas

---

## #17530 — Stanislav Malyshev — 2005-08-04T08:27:07+00:00

URL: https://externals.io/message/17491#17530 · In reply to: #17523

DR>>> How about a __have_prop() method that you can call to find out if a certain
DR>>> virtual property exists?
DR>>
DR>>Works for me, but it needs to be able to called statically (::) and 
DR>>dynamically (->).

I must be missing something, because I don't understand one simple thing: 
if you need mechanism that would allow you classes to know which 
properties they have, and you need custom logic to decide which properties 
exist, why don't you write an interface that has WhatAreMyProperties 
method and implement it in your classes and use it? Why bother with RFCs 
and all __magic stuff? 

-- 
Stanislav Malyshev, Zend Products Engineer
stas@zend.com  http://www.zend.com/ +972-3-6139665 ext.115

---

## #17573 — Ilia Alshanetsky — 2005-08-07T18:07:04+00:00

URL: https://externals.io/message/17491#17573 · In reply to: #17491

Derick Rethans wrote:
> Problems:
> 1. There is no way to document the 'virtual' properties with any of the existing
>    documentation tools (such as phpdoc and doxygen)

Rather then adding abstract properties, why not simply document the 
possible values inside the doc comments ala:
/**
* @var abstract int   Contains all X
*/

> 2. There is no way how the magic methods know if a specific 'virtual' property
>    exists or not as those properties are not declared usually - unless you
>    define an array with property names as a class constant (which is not
>    allowed either).

That's the whole concept behind the feature, if the values were known 
you may as well use clearly declared property and method names.

> 3. There is no way for the magic methods to return a meaningfull error when a
>    property doesn't "exist". Of course it is possible to throw an error with
>    "trigger_error" or "throw" in case a property doesn't "exist" in a specific
>    class, but the file and line numbers would not match the actually get/set
>    action. `debug_backtrace()` can be used to retrieve the correct file and line,
>    but as you have to do this for every class where you want to use setters and
>    getters *and* you have to implement your own error message rendering
>    function this is not really a suitable option either.

How about adding a 3rd optional argument to __get and __set which would 
be an array of acceptable values for the "name" parameter? If there is a 
mismatch a standard warning message will be raised if this parameter was 
supplied.

ilia

---

## #17574 — Derick Rethans — 2005-08-07T18:29:16+00:00

URL: https://externals.io/message/17491#17574 · In reply to: #17573

> Derick Rethans wrote:
> > […]
> 
> Rather then adding abstract properties, why not simply document the possible
> values inside the doc comments ala:
> /**
> * @var abstract int   Contains all X
> */

That would work, if __set and __get were also called for declared 
properties... but they don't do that so you need some keyword - or break 
BC.

> > […]
> 
> That's the whole concept behind the feature, if the values were known you may
> as well use clearly declared property and method names.

True, unless you want to force all property access to go through a 
setter/getter for all declared properties for checks. This is also 
useful for catching typoes:

<?php
    error_reporting(4095);

    class foo {
        public $foo;
    }

    $obj = new foo;
    $obj->fo = 42;
?>

does not throw any notice now for BC reasons.

> > […]
> 
> How about adding a 3rd optional argument to __get and __set which would be an
> array of acceptable values for the "name" parameter? If there is a mismatch a
> standard warning message will be raised if this parameter was supplied.

How does the engine know which list is allowed? The engine is calling 
the __set and __get methods, not users. The whole idea of using a 
keyword here is to provide the engine with such a list.

Derick

---

## #17597 — Roland Tapken — 2005-08-08T12:43:40+00:00

URL: https://externals.io/message/17491#17597 · In reply to: #17573

Hi!

Sorry for wrong threading or if this solution was suggested before... i
currently don't have access to my mail client:)

> 3. There is no way for the magic methods to return a meaningfull error
> when a property doesn't "exist". Of course it is possible to throw an
> error with "trigger_error" or "throw" in case a property doesn't "exist"
> in a specific class, but the file and line numbers would not match the
> actually get/set action. `debug_backtrace()` can be used to retrieve the
> correct file and line, but as you have to do this for every class where
> you want to use setters and
> getters *and* you have to implement your own error message rendering
> function this is not really a suitable option either.

Don't know if this can be implemented... but what's about a 3rd boolean
"handled" call-by-reference-parameter which must be switched to "TRUE" if
the property could be handled? Should be `TRUE` if ommitted for bc reasons,
of course.

greets, Roland

---

## #17598 — Derick Rethans — 2005-08-08T12:55:32+00:00

URL: https://externals.io/message/17491#17598 · In reply to: #17597

> > […]
> 
> Don't know if this can be implemented... but what's about a 3rd boolean
> "handled" call-by-reference-parameter which must be switched to "TRUE" if
> the property could be handled? Should be `TRUE` if ommitted for bc reasons,
> of course.

That was my original idea.

Derick

-- 
Derick Rethans
http://derickrethans.nl | http://ez.no | http://xdebug.org

---

## #17610 — Ilia Alshanetsky — 2005-08-08T14:14:32+00:00

URL: https://externals.io/message/17491#17610 · In reply to: #17574

I got a quick tutorial from Derick :-) on what precisely will be the
affect on the requested functionality and the suggestion makes a whole
lot of sense. As "weird" declaring virtual properties it seems, there is
really no other alternative for solving the outlined problems in a
consistent manner.

Ilia

---

## #17614 — Andrei Zmievski — 2005-08-08T16:52:52+00:00

URL: https://externals.io/message/17491#17614 · In reply to: #17523

> Then you don't do it - it's not a requirement... just an optional thing
> (and ofcourse you can't do the __have_prop() thing then that you
> suggested below.

Why not? _have_prop() should be able to return true if the class does 
handle one of those 1000 properties. They don't need to be declared.

> Works for me, but it needs to be able to called statically (::) and
> dynamically (->).

Shouldn't be a problem, should it?

-Andrei

---

## #17641 — Justin Hannus — 2005-08-09T01:39:12+00:00

URL: https://externals.io/message/17491#17641 · In reply to: #17491

The way ActionScript 2.0 solves this is with set and get keywords on 
function declarations. Any class can contain as many setter/getters as 
they need,. Since we dont want to introduce any new keywords how about 
something similar with __set and __get?

<?php

class Foo
{
	private $_fooProp;

	function __set fooProp($val)
	{
		$this->_fooProp = $val; // $_fooProp is read only
	}

	function __set barProp($val)
	{
		// logic to set barProp...
	}

	function __get barProp($val)
	{
		// logic to get barProp...
	}
}
?>

To allow for BC, if there is no identifier after the __set/__get then 
the existing rules apply.

-Justin

Derick Rethans wrote:
> Hello!
> 
> we're finding some problems with property overloading (__get() and 
> __set()). Here is an RFC describing what we'd like to see changed. 
> Please comment on this.
> 
> 
> Introduction:
> PHP currently supports property overloading with the magic functions __get()
> and __set(). Those methods are called when the code "echo $object->a" or
> "$object->a = 42" are executed and the property "a" is not declared in the
> class. The magic methods are responsibly for:
> - checking if the property actually "exists"
> - setting the value or returning the value depending on the action
> 
> Problems:
> 1. There is no way to document the 'virtual' properties with any of the existing
>    documentation tools (such as phpdoc and doxygen)
> 2. There is no way how the magic methods know if a specific 'virtual' property
>    exists or not as those properties are not declared usually - unless you
>    define an array with property names as a class constant (which is not
>    allowed either).
> 3. There is no way for the magic methods to return a meaningfull error when a
>    property doesn't "exist". Of course it is possible to throw an error with
>    "trigger_error" or "throw" in case a property doesn't "exist" in a specific
>    class, but the file and line numbers would not match the actually get/set
>    action. `debug_backtrace()` can be used to retrieve the correct file and line,
>    but as you have to do this for every class where you want to use setters and
>    getters *and* you have to implement your own error message rendering
>    function this is not really a suitable option either.
> 
> 
> Solutions:
> - For problem 1. we can introduce a keyword (or use an existing one) to define
>   that it is a virtual property ('abstract' or 'virtual' come to mind). When
>   declaring it like this it's easy to document, and we can also implement
>   visibility for those virtual properties.  Marcus already has a patch for
>   this somewhere, which uses the "abstract" keyword for this purpose:
> 
> <?php
> class Base
> {
> 	/**
> 	 * @var int   Contains all X
> 	 */
> 	abstract public $x = 1;
> 	
> 	/**
> 	 * @var int   Contains all Y
> 	 */
> 	abstract protected $y = 2;
> 
> 	//  abstract private $z = 3; abstract properties cannot be private
> }
> ?>
> 
> - In combination to the introduced keyword we need an easy way to check if a
>   passed property name is declared in the class as 'virtual'. Currently (with
>   the 'abstract' keyword properly implemented) you'd have to do:
> 
> <?php
> class Base
> {
> 	abstract public $x = 1;
> 	
> 	function __get($name)
> 	{
> 		try {
> 			$prop = new ReflectionProperty('Base', $name);
> 			if ( !$prop->isAbstract() ) {
> 				/* throw error */
> 			}
> 		} catch ($e) {
> 			/* throw error */
> 		}
> 	}
> }
> 
> $b = new Base();
> echo $b->foo;
> ?>
> 
>   This is ofcourse overly complicated. A better workable solution would be -
>   without breaking BC (suggestions for syntax here are very welcome):
> 
> <?php
> class Base
> {
> 	abstract public $x = 1;
> 	
> 	function __get($name)
> 	{
> 		if (!self::isVirtual($name))) {
> 			/* throw error */
> 		}
> 	}
> }
> 
> $b = new Base();
> echo $b->foo;
> ?>
> 
> - Problem 3 can be solved by:
>   * allowing optional by-ref parameters to the __set
>     and __get function, so that their signatures become:
> 
>     function __set($name, $value [, &$error] )
>     function __get($name [, &$error] )
> 
> 	If the parameter is not given things behave just like they do now -> __set
> 	and __get can not throw meaningful errors with the correct file/line of the
> 	conflicting statement
> 
> 	If the parameter is used in the function's declaration and is set to
> 	"false" when the __set or __get function returns, the engine can throw an
> 	error on the assignment line with the correct file/line combination. If
> 	it's set to "true" (or "null") then the engine should not throw any error.
> 
>   * Use a different __set and __get function for 'abstract' properties, then
>     the engine can already determine if you're doing something wrong before
>     executing the __set and __get methods.
> 
> 
> regards,
> Derick

---

## #17643 — Justin Hannus — 2005-08-09T01:40:46+00:00

URL: https://externals.io/message/17491#17643 · In reply to: #17641

...And, this could allow static member overloading as well!

-Justin

Justin Hannus wrote:
> The way ActionScript 2.0 solves this is with set and get keywords on 
> function declarations. Any class can contain as many setter/getters as 
> they need,. Since we dont want to introduce any new keywords how about 
> something similar with __set and __get?
> 
> <?php
> 
> class Foo
> {
>     private $_fooProp;
> 
>     function __set fooProp($val)
>     {
>         $this->_fooProp = $val; // $_fooProp is read only
>     }
> 
>     function __set barProp($val)
>     {
>         // logic to set barProp...
>     }
> 
>     function __get barProp($val)
>     {
>         // logic to get barProp...
>     }
> }
> ?>
> 
> To allow for BC, if there is no identifier after the __set/__get then 
> the existing rules apply.
> 
> -Justin
> 
> Derick Rethans wrote:
> 
> > […]

---

## #17645 — Justin Hannus — 2005-08-09T02:17:48+00:00

URL: https://externals.io/message/17491#17645 · In reply to: #17641

Please let me correct my last post, and sorry for the double posting :)

Justin Hannus wrote:
> The way ActionScript 2.0 solves this is....
> 
> <?php
> 
> class Foo
> {
>     private $_fooProp;


      function __get fooProp()
      {
          return $this->_fooProp; // $_fooProp is read only
      }

>     function __set barProp($val)
>     {
>         // logic to set barProp...
>     }
> 
      function __get barProp()
      {
          // logic to get barProp...
      }
> }
> ?>
> 
> To allow for BC, if there is no identifier after the __set/__get then 
> the existing rules apply.
> 
> -Justin
> 
> Derick Rethans wrote:
> 
> > […]

---

## #17663 — Derick Rethans — 2005-08-09T07:18:42+00:00

URL: https://externals.io/message/17491#17663 · In reply to: #17614

> 
> 
> > […]
> 
> Why not? _have_prop() should be able to return true if the class does handle
> one of those 1000 properties. They don't need to be declared.

Ah,you meant that __have_prop() should always return the full array of 
things that are supported. That is fine, as long as we can have this 
generated from the "abstract" properties that people declared (so that 
they can be documented properly too).

> > […]
> 
> Shouldn't be a problem, should it?

Nope.

Derick

---

## #17664 — Derick Rethans — 2005-08-09T07:19:44+00:00

URL: https://externals.io/message/17491#17664 · In reply to: #17641

> The way ActionScript 2.0 solves this is with set and get keywords on function
> declarations. Any class can contain as many setter/getters as they need,.
> Since we dont want to introduce any new keywords how about something similar
> with __set and __get?

[...]

> To allow for BC, if there is no identifier after the __set/__get then the
> existing rules apply.

This is all way to complex. 

Derick

---

## #17702 — Andrei Zmievski — 2005-08-09T16:27:45+00:00

URL: https://externals.io/message/17491#17702 · In reply to: #17663

> Ah,you meant that __have_prop() should always return the full array of
> things that are supported. That is fine, as long as we can have this
> generated from the "abstract" properties that people declared (so that
> they can be documented properly too).

No, I meant that prototype for _have_prop() would be:

    bool function _have_prop(string $propname)

_have_prop() should only care about "virtual" properties anyway. You 
pass it a property name, it tells you whether it is a virtual one or 
not.

-Andrei

---

## #18196 — Jeff Moore — 2005-08-17T17:19:37+00:00

URL: https://externals.io/message/17491#18196 · In reply to: #17491

> Problems:
> 1. There is no way to document the 'virtual' properties with any of  
> the existing
>    documentation tools (such as phpdoc and doxygen)

This sounds like a tool problem, not a language problem.

> 2. There is no way how the magic methods know if a specific 'virtual'  
> property
>    exists or not as those properties are not declared usually - unless  
> you
>    define an array with property names as a class constant (which is  
> not
>    allowed either).

Sometimes you just want to know if a single property exists and  
sometimes you want to know all the properties.  There are cases where  
generating the full list of properties may be overly expensive (ORM  
with inheritance).

__has_property($name)
__get_property_list()

Note that some properties may be read only and some might be write  
only, so perhaps incorporating intended use into the API:

__has_readable_property($name)
__has_writable_property($name)
__get_readable_properties()
__get_writable_properties();

> 3. There is no way for the magic methods to return a meaningfull error  
> when a
>    property doesn't "exist". Of course it is possible to throw an  
> error with
>    "trigger_error" or "throw" in case a property doesn't "exist" in a  
> specific
>    class, but the file and line numbers would not match the actually  
> get/set
>    action. `debug_backtrace()` can be used to retrieve the correct file  
> and line,
>    but as you have to do this for every class where you want to use  
> setters and
>    getters *and* you have to implement your own error message rendering
>    function this is not really a suitable option either.

I would rather see exceptions used instead of changing the established  
method signature of __get and __set.  What about defining a standard  
PropertyNotFound exception?



While on the topic, a little wishlisting.  i would like to see an  
accessor method search path, much like Objective C's KeyValueCoding:

http://developer.apple.com/documentation/Cocoa/Conceptual/ 
KeyValueCoding/index.html

so, this defines a read only virtual property:

class Square {
	function __get_area() {
		return $this->width*$this->length;
	}
}

echo $sq->area;

in this case, PHP would look for a __get_XXX method before calling the  
__get as a last resort fallback.  I'm  not attached to this particular  
syntax, but I think the KVC concept with an accessor method naming  
convention has proven worthwhile in Objective C.  KVC also has some  
interesting advanced features such as indexed properties, paths, change  
notification, and constraint enforcement.  KVC is worth emulating.

---

Next page: https://externals.io/message/17491.md?page=2
