Do not implement __call() if you need pass-by-reference of return-by-reference elswhere in your class.
For more information view php bug #25831. Unfortunately this bug is marked wont-fix.
Note that with this class: <?php class SillyClass {
private $config = array();
public function __construct()
{ $this->config['fruit'] = 'banana'; $this->config['animal'] = 'monkey'; $this->config['shoppingList'] =
array('drink' => 'milk', 'food' => 'cheeseburger');
}
//Allow mySillyClass->someProperty style getting of
//anything that might happen to be in the $config array
//(returns NULL if not in the $config array). public function __get($property)
{
if(isset($this->config->$property))
{
return $this->config->$property;
}
}
} ?>
The following code can not be used: <?php
$mySillyClass = new SillyClass(); $drinkToBuy = $mySillyClass->shoppingList->drink; ?>
It seems that although there is no error, $mySillyClass->someProperty->someProperty
does *not* work (__get() is only called once).
It's not really a bug, and I'm sure PHP is behaving properly but it had me stumped for a while!
Simple way to restrict class property access (read and/or write) and range checking on setting, custom get also.
<?php final class test {
protected $x;
protected $y;
protected $z;
private $publicRead = Array( 'x'=>"", 'y'=>"", 'z'=>"getZ" );
private $publicWrite = Array( 'x'=>"setX", 'y'=>"setY" );
final public function test(){ $this->x = 0; $this->y = 0; $this->z = 100;
return $this;
}
final public function setX($val){ //allow only 1 - 10 if ($val > 0 && $val < 11){ $this->x = $val;
} else {
echo "Cannot set X to $val, valid range is 1-10\n<br />";
}
}
final public function setY($val){ //allow only 11 - 20 if ($val > 10 && $val < 21){ $this->y = $val;
} else {
echo "Cannot set Y to $val, valid range is 11-20\n<br />";
}
}
final public function getZ(){
return ($this->z*2)." (x2) ";
}
final private function __get($nm)
{
if (array_key_exists($nm, $this->publicRead)){ $method = $this->publicRead[$nm];
if ($method != ""){//if we have a custom get method use it return $this->$method();
} else { //else return the value directly return $this->$nm;
}
} else {
echo "Cannot get protected property ".get_class($this)."::$nm\n<br />";
return null;
}
}
final private function __set($nm, $val)
{
if (array_key_exists($nm, $this->publicWrite)){ $method = $this->publicWrite[$nm]; $this->$method($val);
} else {
echo "Cannot set protected property ".get_class($this)."::$nm\n<br />";
}
}
}
I am coding a server with a lot of method. To avoid doing a $this->check_auth() call (and others similar processing) in _each_ on my method, I was looking for a way to wrap them all through a dispatch.
Combining _call, with call_user_func_array is the way I did it finally.
So basically, if you want to call "testFunc" you just call $class->test () and
it will be wrapped and testFunc will be executed.
<?php
class MytestClass {
function __call($method, $param)
{ // do anything here return (call_user_func_array (array ("MytestClass", $method."Func"), $param));
}
function testFunc($param, $arg)
{
echo "It works ! Param: $param, ARG=$arg\n";
return true;
}
}
$test = new MytestClass; $test->test ("Cool", "Test");
Коментарии
Do not implement __call() if you need pass-by-reference of return-by-reference elswhere in your class.
For more information view php bug #25831. Unfortunately this bug is marked wont-fix.
I didn't see this posted anywhere, so here it is:
In PHP 4, if you are calling your overloaded class A from inside class B, you MUST include and overload class A before including class B.
I struggled with this one for some time, before attempting to change the include order of the classes, which then worked great.
Note that with this class:
<?php
class SillyClass
{
private $config = array();
public function __construct()
{
$this->config['fruit'] = 'banana';
$this->config['animal'] = 'monkey';
$this->config['shoppingList'] =
array('drink' => 'milk', 'food' => 'cheeseburger');
}
//Allow mySillyClass->someProperty style getting of
//anything that might happen to be in the $config array
//(returns NULL if not in the $config array).
public function __get($property)
{
if(isset($this->config->$property))
{
return $this->config->$property;
}
}
}
?>
The following code can not be used:
<?php
$mySillyClass = new SillyClass();
$drinkToBuy = $mySillyClass->shoppingList->drink;
?>
It seems that although there is no error, $mySillyClass->someProperty->someProperty
does *not* work (__get() is only called once).
It's not really a bug, and I'm sure PHP is behaving properly but it had me stumped for a while!
Simple way to restrict class property access (read and/or write) and range checking on setting, custom get also.
<?php
final class test {
protected $x;
protected $y;
protected $z;
private $publicRead = Array(
'x'=>"",
'y'=>"",
'z'=>"getZ"
);
private $publicWrite = Array(
'x'=>"setX",
'y'=>"setY"
);
final public function test(){
$this->x = 0;
$this->y = 0;
$this->z = 100;
return $this;
}
final public function setX($val){
//allow only 1 - 10
if ($val > 0 && $val < 11){
$this->x = $val;
} else {
echo "Cannot set X to $val, valid range is 1-10\n<br />";
}
}
final public function setY($val){
//allow only 11 - 20
if ($val > 10 && $val < 21){
$this->y = $val;
} else {
echo "Cannot set Y to $val, valid range is 11-20\n<br />";
}
}
final public function getZ(){
return ($this->z*2)." (x2) ";
}
final private function __get($nm)
{
if (array_key_exists($nm, $this->publicRead)){
$method = $this->publicRead[$nm];
if ($method != ""){//if we have a custom get method use it
return $this->$method();
} else { //else return the value directly
return $this->$nm;
}
} else {
echo "Cannot get protected property ".get_class($this)."::$nm\n<br />";
return null;
}
}
final private function __set($nm, $val)
{
if (array_key_exists($nm, $this->publicWrite)){
$method = $this->publicWrite[$nm];
$this->$method($val);
} else {
echo "Cannot set protected property ".get_class($this)."::$nm\n<br />";
}
}
}
$t = new test;
$t->x = 1;
$t->y = 113;
$t->z = 1001;
echo "<br /><br />";
echo "X:".$t->x."<br />";
echo "Y:".$t->y."<br />";
echo "Z:".$t->z."<br />";
?>
I am coding a server with a lot of method. To avoid doing a $this->check_auth() call (and others similar processing) in _each_ on my method, I was looking for a way to wrap them all through a dispatch.
Combining _call, with call_user_func_array is the way I did it finally.
So basically, if you want to call "testFunc" you just call $class->test () and
it will be wrapped and testFunc will be executed.
<?php
class MytestClass
{
function __call($method, $param)
{
// do anything here
return (call_user_func_array (array ("MytestClass", $method."Func"), $param));
}
function testFunc($param, $arg)
{
echo "It works ! Param: $param, ARG=$arg\n";
return true;
}
}
$test = new MytestClass;
$test->test ("Cool", "Test");
?>