Consider below working code :
<?php
class PropertyTest {
/** Location for overloaded data. */
private $data = array();
/** Overloading not used on declared properties. */
public $declared = 1;
/** Overloading only used on this when accessed outside the class. */
private $hidden = 2;
public function __set($name, $value) {
echo "Setting '$name' to '$value'
";
$this->data[$name] = $value;
}
public function __get($name) {
echo "Getting '$name'
";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
var_dump($trace); die;
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
/** As of PHP 5.1.0 */
public function __isset($name) {
echo "Is '$name' set?
";
return isset($this->data[$name]);
}
/** As of PHP 5.1.0 */
public function __unset($name) {
echo "Unsetting '$name'
";
unset($this->data[$name]);
}
/** Not a magic method, just here for example. */
public function getHidden() {
return $this->hidden;
}
}
echo "<pre>
";
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "
";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "
";
echo $obj->declared . "
";
echo "Let's experiment with the private property named 'hidden':
";
echo "Privates are visible inside the class, so __get() not used...
";
echo $obj->getHidden() . "
";
echo "Privates not visible outside of class, so __get() is used...
";
echo $obj->hidden . "
";
?>
Output :
Setting 'a' to '1'
Getting 'a'
1
Is 'a' set?
bool(true)
Unsetting 'a'
Is 'a' set?
bool(false)
1
Let's experiment with the private property named 'hidden':
Privates are visible inside the class, so __get() not used...
2
Privates not visible outside of class, so __get() is used...
Getting 'hidden'
Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29
I understood everything in the code. I only have a concern in accessing the private property $hidden
outside the class using magic method __get()(or some other way but in overloading). I mean by usage of Overloading only.
But currently I'm not able to achieve that. Getting User Notice for the same.
I don't understand your problem
<?php
class TestClass{
private $private = 'true';
public function __get($key){
if( isset($this->{$key}) ){
return $this->{$key};
}
throw new Exception('Undefined object property '.__CLASS__.'::'.$key);
}
}
echo (new TestClass())->private;
Outputs
true
See for yourself here
There is no reason you can't do that from the class where $private
is defined in. That said it's probably a poor design choice.
Now if you are trying to do this ( Access private parent property from a child )
<?php
class TestClass{
private $private = 'true';
}
class ChildClass extends TestClass{
public function __get($key){
if( isset($this->{$key}) ){
return $this->{$key};
}
throw new Exception('Undefined object property '.__CLASS__.'::'.$key);
}
}
echo (new ChildClass())->private;
Outputs ( our exception )
<b>Fatal error</b>: Uncaught Exception: Undefined object property ChildClass::private in
See it here
Indeed, and if you want to get real Crazy you can do this:
<?php
class TestClass{
private $private = 'true'; //not visible to child
//called -via- child class
public function parentEcho(){
echo "
Parent: {$this->private}
";
return $this; //return this for chaining
}
}
class ChildClass extends TestClass{
private $private = 'false'; //this is not parent::$private
public function childEcho(){
echo "
Child: {$this->private}
";
return $this;
}
}
(new ChildClass())->childEcho()->parentEcho();
Outputs
Child: false
Parent: true
Check this out here
This illustrates the scope of a private
property Is only within this
class. Even children know nothing about it. However with a method in parent that accesses is directly ( not overwritten in child ) it can still be reached by inheritance. Because, the child inherits the method and the method is defined within the class ( parent ) which can access it.
But if you truly want your mind blown (Reflection):
<?php
class TestClass{
private $private = 'true';
public function parentEcho(){
echo "
Parent: {$this->private}
";
return $this;
}
}
$Obj = new TestClass();
$Obj->parentEcho();
echo "
";
$ReflectionObj = new ReflectionObject($Obj);
$ReflectionProperty = $ReflectionObj->getProperty('private');
$ReflectionProperty->setAccessible(true);
echo $ReflectionProperty->getValue($Obj)."
";
$ReflectionProperty->setValue($Obj, 'false' );
echo $ReflectionProperty->getValue($Obj)."
";
$Obj->parentEcho();
Outputs
Parent: true
true
false
Parent: false
You can see this darling here
Reflection allows you to inspect the definition of other Objects, methods, function etc... (introspection) from outside of them. I am not to sure with recent versions of PHP, but in the past their was a significant performance hit when using reflection (it wasn't like seconds, more like 10s of milliseconds ). However, there are some really neat things you can do with it.
http://php.net/manual/en/intro.reflection.php
That all said, you can access it with a simple get
method, and semantically that is probably the best way.
public method getProperty() {
return $this->property;
}
public method setProperty($property) {
return $this->property = $property;
}
A few things I feel I must mention
I rarely, rarely, rarely ever use private
properties. The problem with private properties is if you decide to extend the class, later, you'll wind up changing most of them over to protected
anyway. private - visible only within the scope of this
class.
I use protected
Something like 99%
of the time. It just works. protected - visible only within the scope of this class's descendants.
I refuse to use public
properties as it's a poor design, IMO, that leads to a lot of woes when it comes time to maintain your code. Classes should be Black Boxes
, which means the internal workings of them should not be exposed to the rest of your code. The problem with exposing all the workings of you class is you could rename a property without thinking and break some piece of code somewhere. At least with public methods you can rename the properties, re-work the method and nothing outside the class should be affected (as long as the method name, inputs, and outputs don't change) public - visible within the scope of the caller (and class's descendants)
Cheers, and happy coding.