Abstract static property cannot be overwritten? - php

abstract class Ghost {
protected static $var = 'I\'m a ghost';
final public static function __callStatic($method, $args = array()) {
echo self::$var;
}
}
class Person extends Ghost {
protected static $var = 'I\'m a person';
}
The call of Person::whatever() will print: I'm a ghost.
Why?

You're looking for something called Late Static Binding, which requires PHP 5.3+

"self" is used by Current class,
if you want get child static property, use "static" as :
final public static function __callStatic($method, $args = array()) {
echo **static**::$var;
}

Related

Getting properites of static class in static function?

I just wanna get return class properties in not instantiated class use. There is no way to instance this class? Please tell me...!
My example is below↓↓
<?php
class MyTest {
public static $test1 = 'a';
public static $test2 = 'b';
public static function getProperties() {
//how to code here...?
}
}
//plz return $test1, $test2
MyTest::getProperties();
Use self:: to access static properties:
public static function getProperties() {
return [self::$test1, self::$test2];
}

Access variable inside class

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);

Call static properties within another class in php

I have problem about calling a static property of a class inside another class.
Class A {
public $property;
public function __construct( $prop ) {
$this->property = $prop;
}
public function returnValue(){
return static::$this->property;
}
}
Class B extends A {
public static $property_one = 'This is first property';
public static $property_two = 'This is second property';
}
$B = new B( 'property_one' );
$B->returnValue();
I expect to return This is first property But the Output is just the name a parameter input in __construct;
When I print_r( static::$this->property ); the output is just property_one
Just change:
return static::$this->property;
with:
return static::${$this->property};
Maybe like this?
<?php
Class A {
public $property;
public function __construct( $prop ) {
$this->property = $prop;
print static::${$this->property};
}
}
Class B extends A {
public static $property_one = 'This is first property';
public static $property_two = 'This is second property';
}
$B = new B( 'property_one' );
(I mean you can access (print,...) the property this way, but the constructor will return an object anyway.)
There are several issues here:
the static property $property_one is declared in class B, the A class's constructor won't have access to that property, nor can you guarantee this property to be present.
Granted, since PHP 5.3, late static binding is supported, but that doesn't change the fact that you're never going to be sure that some static property that just happens to be called whatever $this->property happens to be assigned. What if it's assigned an object? an int, or float?
You access a static property like this: static::$propery or self::$property. Note the $! When you write static::$this->property, you're expecting this to evaluate to self::property_one. You're clearly missing the $ sign.
The very least you need is self::${$this->property}. Check the PHP manual on variable variables.
You're attempting to return a string from a constructor function, that's not possible. A constructor must, must return an instance of the class. Any return statements that don't will be ignored.
To have access to a static property of a child class in the constructor, you can't but rely on the child's constructor:
Class A
{
public $property;
}
Class B extends A
{
public static $property_one = 'This is first property';
public static $property_two = 'This is second property';
public function __construct( $prop )
{
$this->property = $prop;
print self::${$this->property};
}
}
$B = new B( 'property_one' );
An alternative would be:
Class A
{
public $property;
public function __constructor($prop)
{
$this->property = $prop;
}
public function getProp()
{
return static::${$this->property};
}
}
Class B extends A
{
public static $property_one = 'This is first property';
public static $property_two = 'This is second property';
}
$B = new B( 'property_one' );
$B->getProp();

Why doesn't late static binding work with variables in PHP 5.3?

Let's start off with some code:
class Super {
protected static $color;
public static function setColor($color){
self::$color = $color;
}
public static function getColor() {
return self::$color;
}
}
class ChildA extends Super { }
class ChildB extends Super { }
ChildA::setColor('red');
ChildB::setColor('green');
echo ChildA::getColor();
echo ChildB::getColor();
Now, late static binding in PHP 5.3 using the static keyword works great with static methods, so I assumed it would do the same magic on static variables. Well, seems it doesn't. The example above does not print out "red" and then "green" as I first expected, but "green" and "green". Why doesn't this work on variables when it works on methods? Is there any other way to achieve the effect I expected?
Late static binding will only work for new definitions of variables / methods. Thus, in your example, the $color property of Super will always be modified instead of ChildA or ChildB. To make use of late static binding, you need to use the static keyword instead of self. Furthermore, you need to redefine the $color property of your ChildA and ChildB classes:
class Super {
protected static $color;
public static function setColor($color){
// static instead of self
static::$color = $color;
}
public static function getColor() {
// static instead of self
return static::$color;
}
}
class ChildA extends Super {
protected static $color;
}
class ChildB extends Super {
protected static $color;
}
ChildA::setColor('red');
ChildB::setColor('green');
echo Super::getColor(); // prints nothing (NULL = ''), expected
echo ChildA::getColor();// prints red
echo ChildB::getColor();// prints green

Dynamically populating a static variable in PHP

I have two static values: "type" and "typeID". Type is human readable and constant, and typeID needs to be looked up from the database, based on the value of type. I need the lookup to happen once, when the class definition is first loaded
To illustrate, here is some code that doesn't work because you can't call functions in the declaration space.
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = MyClass::lookupTypeID(self::$type);
}
Is there a magic method that is called exactly once when the class definition is loaded? If there is something obvious I'm missing it.
shamelessly pulled from the php manual's static keyword comments:
Because php does not have a static constructor and you may want to initialize static class vars, there is one easy way, just call your own function directly after the class definition.
for example.
<?php
function Demonstration()
{
return 'This is the result of demonstration()';
}
class MyStaticClass
{
//public static $MyStaticVar = Demonstration(); //!!! FAILS: syntax error
public static $MyStaticVar = null;
public static function MyStaticInit()
{
//this is the static constructor
//because in a function, everything is allowed, including initializing using other functions
self::$MyStaticVar = Demonstration();
}
} MyStaticClass::MyStaticInit(); //Call the static constructor
echo MyStaticClass::$MyStaticVar;
//This is the result of demonstration()
?>
Simple and no magic needed, don't forget you can always define a variable as null and test that it is null (doing the db call only then). Then it's just a matter if you want that to happen when the class is constructed or included (include_once etc...)
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
if(is_null(self::$typeID)){
self::lookupTypeID(self::$type);
}
}
public static lookupTypeID($type){
self::$typeID = //result of database query
}
}
or
MyClass::lookupTypeID(); //call static function when class file is included (global space)
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
}
public static lookupTypeID($type=null){
if(is_null($type)){
$type = self::$type;
}
self::$typeID = //result of database query (SELECT somefield FROM sometable WHERE type=$type) etc..
}
}
a static constructor is more like a factory method
if(!function_exists(build_myclass)){
function build_myclass(){
return MyClass::build();
}
}
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
}
public static function build(){
return new self(); //goes to __construct();
}
}
$class = new MyClass(); //or
$class = MyClass::build(); //or
$class = build_myclass();
Such a thing would normally be called a "static constructor", but PHP lacks such things. You might want to consider one of the workarounds suggested in the PHP manual comments, e.g. http://www.php.net/manual/en/language.oop5.static.php#95217

Categories