Find the property's scope within class - php

class ParentClass
{
public function list()
{
foreach ($this as $property => $value)
{
if (is_public($this->$property))
echo 'public: ';
else if (is_protected($this->$property))
echo 'protected: ';
echo "$property => $value" . PHP_EOL;
}
}
}
class ChildClass extends ParentClass
{
protected $Size = 4;
protected $Type = 4;
public $SubT = 1;
public $UVal = NULL;
}
$CC = new ChildClass;
$CC->list();

Using ReflectionProperty, it's possible. You could create a helper function if you want to make it less verbose:
<?php
function P($obj, $name)
{
return new ReflectionProperty($obj, $name);
}
class Foo
{
public $a;
public function __construct()
{
foreach (array_keys(get_object_vars($this)) as $name)
{
if (P($this, $name)->isPublic())
{
echo "Public\n";
}
}
}
}
new Foo();
?>

Related

PHP: Get Acces To Private Variable In Class

I've been doing a project in PHP for the last few hours and I have encountered into a problem.
The problem is I don't know how to access private variables in a class and I can't find it online.
Example:
<?php
class Example{
private $age;
public function __construct() {
$age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->$age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
As far as I know, I should be able to access the variable with $this->$age but it isn't working.
Thank you.
EDIT: Got it working with help of the awesome stackoverflooooooooow community, this is how a working one looks.
<?php
class Example{
private $age;
public function __construct() {
$this->age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
Look at this approach.
first: create Entity that stores and retrieves data inside of private $attributes array, and with magic __set(), __get() You can also do like: $object->variable = 123
second: extend Entity with Human class and add some function specific to child class (for example hasValidAge()):
<?php
class Entity {
private $attributes;
public function __construct($attributes = []) {
$this->setAttributes($attributes);
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
return $this;
}
public function setAttributes($attributes = []) {
foreach($attributes AS $key => $value) {
$this->setAttribute($key, $value);
}
}
public function getAttribute($key, $fallback = null) {
return (isset($this->attributes[$key]))?
$this->attributes[$key] : $fallback;
}
public function __get($key) {
return $this->getAttribute($key);
}
public function __set($key, $value) {
$this->setAttribute($key, $value);
}
}
class Human extends Entity {
public function __construct($attributes = []) {
$this->setAttributes($attributes);
$this->checkAge();
}
public function hasValidAge() {
return ($this->getAttribute('age') > 12)? true : false;
}
}
$boy = new Human(['name' => 'Mark', 'age' => 14]);
if($boy->hasValidAge()) {
echo "Welcome ".$boy->name."!";
}
?>
p.s. I've removed echo "Welcome!" part from constructor because it's not cool to do echo from model object, in our example Human is model of Entity.

Special class value in PHP

Some code:
class MyClass
{
public function __get($key)
{
return $this[$key];
}
public function __set($key, $value)
{
$this[$key] = $value;
}
}
$m = new MyClass();
$m->name = 'This is my class.';
OR
$m['name'] = 'This is my class.';
But not working. Somebody can help me?
In order to be able to access values in your class using array access, you have to implement the ArrayAccess interface. In order to also arbitrary property names dynamically, copy the sample code from that page. Once you've implemented the ArrayAccess methods your __get and __set will work as-is.
<?php
class obj implements arrayaccess {
private $container = array();
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
public function __get($key) {
return $this[$key];
}
public function __set($key, $value) {
$this[$key] = $value;
}
}
$foo = new obj();
$foo->pill = 123;
var_dump($foo->pill);
The problem you are having is that inside the __get and __set methods, you are accessing the properties as an array. You need to use $this->$key instead of $this[$key].
class MyClass
{
public function __get($key)
{
return $this->$key;
}
public function __set($key, $value)
{
$this->$key = $value;
}
}
$m = new MyClass();
echo "before set: \n";
var_dump($m);
$m->foo = "bar";
echo "after set: \n";
var_dump($m);
Example: http://codepad.viper-7.com/oNLbzq
Try this approach
class MyClass
{
private $m_var_data = array();
public function __set($p_name, $p_value)
{
$this->m_var_data[$p_name] = $p_value;
}
public function __get($p_name)
{
if (array_key_exists($p_name, $this->m_var_data))
{
return $this->m_var_data[$p_name];
}
}
}
$m = new MyClass();
$m->name = 'This is my class.';
In order to create a new property, you should do this:
class MyClass
{
private $data = array();
public function __set($name, $value)
{
echo "Setting '$name' to '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Getting '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
}
}
Then you can overload properties as you want in your example.
This link can give you more references:
http://www.php.net/manual/pt_BR/language.oop5.overloading.php#language.oop5.overloading.members

Copy a class into another

I have
class A
{
$a;
$b;
$c
}
And
class B
{
$a;
$b;
$e;
$f
}
How can i copy all common property from A to B? I already try the clone method but it only give me 2 objects A.
Is there any way to do it generically?
If you're looking for class "copying", then do it via overriding via extends keyword:
class A
{
public $a, $b, $c;
}
class B extends A
{
public $d, $e, $f;
}
-now your B will inherit all properties from A which are not private (so $a, $b and $c as well)
But if it's about objects (for example, your classes are not related anyhow) - then use get_object_vars() to iterate:
class A
{
public $a=1;
public $b=2;
public $c=3;
}
class B
{
public $a=5;
public $b=6;
public $e=7;
public $f=8;
}
$foo = new A;
$bar = new B;
foreach(get_object_vars($foo) as $name=>$value)
{
if(property_exists($bar, $name))
{
$bar->$name = $value;
}
}
-check the fiddle. Note, that properties must be visible (public) to do this.
First way (inheritance) http://www.php.net/manual/en/language.oop5.inheritance.php
<?php
class A {
public $_x = 'x';
public $_y = 'y';
public $_z = 'zz';
}
class B extends A {
public function __construct() {
echo $this->_x . "__" . $this->_y . "__" . $this->_z;
}
}
$b = new B; // x__y__zz
?>
Second way - class instantiation - properties are public, so you can access their values from the object instance, and assign it to you inner properties
<?php
class AA {
public $_x = 'x';
public $_y = 'y';
public $_z = 'zz';
}
class BB {
public $_x, $_y, $_z;
private $_AA;
public function __construct() {
$this->_AA = new AA();
$this->_x = $this->_AA->_x;
$this->_y = $this->_AA->_y;
$this->_z = $this->_AA->_z;
echo $this->_x . "__" . $this->_y . "__" . $this->_z;
}
}
$bb = new BB; // x__y__zz
?>
Third way, if properties are private, and if you have direct access to the base class, you can make accessors to then, so even they cannot be overwritten from outside, their value can be accessed
<?php
class AAA {
private $_x = 'x';
private $_y = 'y';
private $_z = 'zz';
public function getX() {
return $this->_x;
}
public function getY() {
return $this->_y;
}
public function getZ() {
return $this->_z;
}
}
class BBB {
public $_x, $_y, $_z;
private $_AAA;
public function __construct() {
$this->_AAA = new AAA();
$this->_x = $this->_AAA->getX();
$this->_y = $this->_AAA->getY();
$this->_z = $this->_AAA->getZ();
echo $this->_x . "__" . $this->_y . "__" . $this->_z;
}
}
$bbb = new BBB; // x__y__zz
Generic :)
<?php
class AAA {
private $_x = 'x';
private $_y = 'y';
private $_z = 'zz';
public function getX() {
return $this->_x;
}
public function getY() {
return $this->_y;
}
public function getZ() {
return $this->_z;
}
}
class BBB {
public $_x, $_y, $_z;
}
$AAA = new AAA();
$BBB = new BBB();
$get = 'get';
$arr_AAA = (array)$AAA;
foreach($arr_AAA as $key => $value) {
$property = explode('_', $key);
$property = ucfirst($property[1]);
$getter[] = $get.$property;
}
$i = 0;
foreach (get_object_vars($BBB) as $k=>$v) {
$get = $getter[$i];
$BBB->$k = $AAA->$get();
$i++;
}
var_dump($BBB);
/**
object(BBB)[2]
public '_x' => string 'x' (length=1)
public '_y' => string 'y' (length=1)
public '_z' => string 'zz' (length=2)
*
*/
This should work for i.e.
private $_qwe = 'qwe';
public getQwe() {
return $this->_qwe;
}
It will uppercase the first letter as it should be the convention of the getters. Ofcourse you can build your own convention.

Place _construct inside a if()

Is there a way to :
class foo {
private $skey;
if(isset($_SESSION['some_val']) {
function __construct(){
$skey = 'something';
}
}
}
I just want to create the initial value of $key (something), if the $_SESSION['some_val'] doesn't exist.
Thanks in advance
edit:
this is what I did with your help
function __construct() {
if(!isset($_SESSION['skey'])) {
$tp = new Text_Password();
$skey = $tp->create();
$this->skey = $skey;
$_SESSION['skey'] = $this->skey;
}
}
Nope. However, you can simply do this:
class foo {
function __construct()
{
if(isset($_SESSION['some_val'])
{
$this->key = 'something';
}
}
}
No, that's impossible. You could do this:
class foo {
private $key;
function __construct(){
if (isset($_SESSION['some_val']) {
$this->key = 'something';
} else {
$this->key = null;
}
}
}
Or better, use a parametrised constructor and leave the $_SESSION stuff in you main application:
class foo {
private $key;
function __construct($init = null){
$this->key = $init;
}
}
Then in your main app:
if (isset($_SESSION['some_val'])) {
$f = new foo('something');
} else {
$f = new foo();
}
You should just put inside the construct method.
class foo {
private $key;
public function __construct(){
if(isset($_SESSION['some_val']) {
$this->key = 'something';
}
}
}

Attribute reference does not work with inheritence

I'm stuck with a behaviour of PHP which I can't seem to understand.
class A {
private $v;
public function __construct(&$v)
{
$this->v = &$v;
}
public function setV($v) {
$this->v = $v;
}
public function getV() {
return $this->v;
}
}
class B extends A {
public function setV($v) {
$this->v = $v;
}
}
$v = '1';
$c = new A($v); // <= this will be replaced
echo $c->getV() . "\n";
$v = '2';
echo $c->getV() . "\n";
$c->setV('3');
echo $c->getV() . "\n";
echo $v . "\n";
Outputs
1
2
3
3
But when I replace the object creation with $c = new B($v); it outputs
1
2
2
2
I would expect the same output as before. Why is this? I use PHP 5.3 but probably update to try to fix this.
When a class extends another parent class it can only use public and protected variables and functions from the parent class..
So this will print the same result ;
<?php
class A {
private $v;
public function __construct(&$v)
{
$this->v = &$v;
}
public function setV($v) {
$this->v = $v;
}
public function getV() {
return $this->v;
}
}
class B extends A {
public function setV($v) {
parent::setV($v);
}
}
$v = '1';
$c = new B($v); // <= this will be replaced
echo $c->getV() . "\n";
$v = '2';
echo $c->getV() . "\n";
$c->setV('3');
echo $c->getV() . "\n";
echo $v . "\n";
?>
you use $c = new B($v) but class B has no constructor then why you pass the parameter $v. use parent's constructor and try :
class B extends A{
public function __construct($v)
{
parent::_construct($v)
}
}
then try with your replacement.

Categories