I have been see this come up alot i think it has todo with late static binding but whats the point of doing it this way.
class {
public static $name = array();
function something() {
static::$name;
}
}
over
class {
public static $name = array();
function something() {
self::$name;
}
}
self::$name in the parent class will always refer to the parent class' property whereas static::$name in the parent class will refer to the property of the runtime class.
For example
class A
{
protected static $foo = 'foo';
public static function getSelfFoo()
{
return self::$foo;
}
public static function getStaticFoo()
{
return static::$foo;
}
}
class B extends A
{
protected static $foo = 'bar';
}
echo A::getSelfFoo(); // 'foo'
echo A::getStaticFoo(); // 'foo'
echo B::getSelfFoo(); // 'foo'
echo B::getStaticFoo(); // 'bar'
It matters if you create a subclass of your class. In your first example, the something function will refer to the $name variable on the subclass. In your second example it will refer to the $name variable on the base class.
Related
I have two classes (Model and User) but I have a problem so I have tried to explain it in a simple example :
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
protected static $todo ="studing";
}
$s = new student();
$s->get_what_todo(); // this will show the word (nothing)
//but I want to show the word (studing)
Please give me a solution but without writing any function in the student class I only want to make declarations there :) and thank you :)
The principle is called "late static binding", and was introduced in PHP 5.3.0; with the self keyword to access the property defined in the calling class within the inheritance tree, or static to access the property defined in the child class within that inheritance tree.
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo static::$todo; // change self:: to static::
}
}
class student extends person
{
protected static $todo ="studying";
}
class teacher extends person
{
protected static $todo ="marking";
}
class guest extends person
{
}
$s = new student();
$s->get_what_todo(); // this will show the "studying" from the instantiated child class
$t = new teacher();
$t->get_what_todo(); // this will show the "marking" from the instantiated child class
$g = new guest();
$g->get_what_todo(); // this will show the "nothing" from the parent class,
// because $todo is not overriden in the child class
The reliable way to override a static variable is to do it by redeclaring it. Some people may suggest modifying it in the construct method, but I don't think that's reliable.
It won't reflect the changes until the class is constructed at least once. And of course, in class methods, don't forget to call the static variable using "static::" instead of "self::" when you want to always access the overridden variable.
Here's an example of what I mean:
The class Foo is the base class, the class Bar is changing the variable inside its constructor, and the class Baz is overriding the variable in its declaration.
class Foo
{
public static $a = "base";
}
class Bar extends Foo
{
function __construct()
{
self::$a = "overridden";
}
}
class Baz extends Foo
{
public static $a = "overridden";
}
echo 'Foo: ' . Foo::$a . '<br>';
echo 'Bar: ' . Bar::$a . '<br>';
echo 'Baz: ' . Baz::$a . '<br>';
new Bar();
echo 'Bar after instantiation: ' . Bar::$a;
This is the output from phptester.net
Foo: base
Bar: base
Baz: overridden
Bar after instantiation: overridden
As you can see, Bar's way of changing the variable isn't taking effect until after the constructor is called at least once.
EDIT: However, there is another way to edit a variable permanently and reliably: do it after the class declaration. This is especially handy if you only need to modify a variable and not completely override it, like for example an array. It feels a bit dirty, but in theory should work everytime.
class Foo
{
public static $a = [
'a' => 'a'
];
}
class Bar extends Foo
{
public static $a;
}
Bar::$a = Foo::$a;
Bar::$a['b'] = 'b';
echo 'Foo: ' . print_r(Foo::$a, true) . '<br>';
echo 'Bar: ' . print_r(Bar::$a, true) . '<br>';
This is the output from phptester.net
Foo: Array ( [a] => a )
Bar: Array ( [a] => a [b] => b )
EDIT 2: This last method also gets picked up by ReflectionClass::getStaticPropertyValue in my tests.
you can try set variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
self::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();
you can try set parent variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
parent::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();
I'm new in OO php, and I'm trying to access $my_array string (or it is a property):
class Something extends MAIN
{
private static $instance;
public static function newInstance()
{
if( !self::$instance instanceof self ) {
self::$instance = new self;
}
return self::$instance;
}
function __construct()
{
parent::__construct();
$my_array = array('test1','test2');
}
}
Tried with this:
$int = Something::newInstance();
echo $int->my_array;
echo Something::my_array
But nothing works. What is the problem? EDIT: I must mention that I shouldn't change anything inside Something class. Or it is impossible to do this without making a change inside Soemthing class?
$my_array is local to the constructor . You'll need to declare it in such a way that it has the scope of class. You'll have to do it as
class Something extends MAIN
{
private static $instance;
public $my_array = array();
// Rest code
}
$my_array is now a local variable in your method (=function in a class) and therefor cannot be read outside of that method. Change it like this to make it a 'property'*) of the object.
class Something extends MAIN
{
private static $instance;
public $my_array;
function newInstance() { ... } // Left out for brevity
function __construct()
{
parent::__construct();
// Use $this to reference the instance, in the way that self references the class.
$this->my_array = array('test1','test2');
}
}
Then use
$int = Something::newInstance();
echo $int->my_array;
*) PHP calls it a property, but in most languages a property is a definition that referes to getter and setter methods or directly to an (often private) variable in the class. In PHP, that variable itself is called a property.
class Something extends MAIN {
private static $instance;
public static $my_array;
public static
function newInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
function __construct() {
parent::__construct();
self::$my_array = array('test1', 'test2');
}
}
You can assign a value to $my_array directly without to be in the constructor function.
public static $my_array = array('test1', 'test2');
and remove this line from constructor
self::$my_array = array('test1', 'test2');
When usage:
$int = Something::newInstance();
print_r(Something::$my_array);
I have tried in yii frame work adding set function in CController and try to add property in controller's object but it gives error
Can i user base class's __set function to set property of a instance.
Class Base {
public function __set() {
$this->$name = $value;
}
}
Class SubClass1 extends Base{
}
Class SubClass2 extends Base {
}
I create instance of SubClass1 or SubClass2 and i want to add property dynamically. Is it possible.
yes you can unless the property is private
Yes you can place your magic function your your class structure. Magic functions normally calls even if you are not defining in class file.
So, if you not create __set() in your class file, it won't affect much. But, if you want to do some extra things while setting under object then it will be helpful.
Also, __set() function need two parameter, $name and $value. Please refer following url,
__set() magic function
Regards
You can indeed, the following will demonstrate:
<?php
class Foo
{
private $vars = array();
public function __set($name, $value)
{
echo "Setting $name: $value<br />";
$this->vars[$name] = $value;
}
public function __get($name)
{
echo "Getting $name<br />";
return isset($this->vars[$name]) ? $this->vars[$name] : null;
}
}
class Bar extends Foo {}
$bar = new Bar();
$bar->baz = 'baz';
echo $bar->baz;
Which will output:
Setting baz: baz
Getting baz
baz
class Base {
protected $data;
public function __construct() {
$this->someMethodBaseClass();
}
protected function someMethodBaseClass() {
$this->data = 123456;
}
}
class subclass1 extends Base{
public function __construct() {
parent::__construct();
}
public function getData() {
return $this->data;
}
}
is it possible to easily and quickly "assigning properties of one object to another"
class a {
public $number_one;
public $number_two;
public $number_three;
function __contruct() {
//do stuff
}
}
class b {
public $my_var;
function __contruct() {
$instanc_a = new a();
extract( $instance ); // but make these extracted object properties of class b????
// how? :-(
echo $this->number_one;
}
}
You can use get_object_vars to copy the public (only) properties of class a to the current object:
class b {
public $my_var;
function __construct() {
$instanc_a = new a();
$vars = get_object_vars($instanc_a);
foreach($vars as $name => $value) {
$this->$name = $value;
}
echo $this->number_one;
}
}
See it in action.
Note: You have a typo in your code (two cases of "contruct" instead of "construct") which will prevent things from working as they should.
Sounds like you actually want class b to extend class a
class b extends a {
public $my_var;
function __construct () {
parent::__construct();
// Now $this refers to anything in class b, or if it doesn't exist here, looks to class a for it
echo $this->number_one;
}
}
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo parent::$bb; //Fatal error: Undefined class constant 'bb'
}
}
$test = new B($some);
$test->childfunction();
Question:
How do I display parent variable in child?
expected result will echo 'parent bb'
echo $this->bb;
The variable is inherited and is not private, so it is a part of the current object.
Here is additional information in response to your request for more information about using parent:::
Use parent:: when you want add extra functionality to a method from the parent class. For example, imagine an Airplane class:
class Airplane {
private $pilot;
public function __construct( $pilot ) {
$this->pilot = $pilot;
}
}
Now suppose we want to create a new type of Airplane that also has a navigator. You can extend the __construct() method to add the new functionality, but still make use of the functionality offered by the parent:
class Bomber extends Airplane {
private $navigator;
public function __construct( $pilot, $navigator ) {
$this->navigator = $navigator;
parent::__construct( $pilot ); // Assigns $pilot to $this->pilot
}
}
In this way, you can follow the DRY principle of development but still provide all of the functionality you desire.
Just echo it since it's inherited
echo $this->bb;
With parent::$bb; you try to retrieve the static constant defined with the value of $bb.
Instead, do:
echo $this->bb;
Note: you don't need to call parent::_construct if B is the only class that calls it. Simply don't declare __construct in B class.
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo parent::$this->bb; //works by M
}
}
$test = new B($some);
$test->childfunction();`
$bb has now become the member of class B after extending class A.
So you access $bb like it's an attribute of class B.
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo $this->bb;
}
}
$test = new B($some);
$test->childfunction();
all the properties and methods of the parent class is inherited in the child class so theoretically you can access them in the child class but beware using the protected keyword in your class because it throws a fatal error when used in the child class.
as mentioned in php.net
The visibility of a property or method
can be defined by prefixing the
declaration with the keywords public,
protected or private. Class members
declared public can be accessed
everywhere. Members declared protected
can be accessed only within the class
itself and by inherited and parent
classes. Members declared as private
may only be accessed by the class that
defines the member.
PHP Accessing Parent Class Protected Variable & Methods
class A {
protected $bb = 'parent bb';
protected function sayHello(){
echo 'Say Hello';
}
}
class B extends A {
public function childfunction() {
echo $this->bb.'<br>';
echo $this->sayHello();
}
}
$test = new B();
$test->childfunction();
Through parent class contructor you can pass data to parent class from child class. Have a look below example for better understanding
<?php
class Student
{
public $name;
function __construct($name){
$this->name = $name;
}
}
class Test extends Student
{
public $age;
function __construct($name,$age){
$this->age = $age;
parent::__construct($name);
}
}
$obj = new Test("sajib khan" ,21);
echo $obj->name;
echo $obj->age;
?>
class A {
private $points = 100;
public function getPoints() {
return $this->points;
}
}
class B extends A {
protected $points = 70;
public function getPoints() {
return parent::getPoints();
}
}
$element = new B();
echo $element->getPoints();
change the visibility private or protected for test