How to access constant defined in child class from parent class functions? - php

I saw this example from php.net:
<?php
class MyClass {
const MY_CONST = "yonder";
public function __construct() {
$c = get_class( $this );
echo $c::MY_CONST;
}
}
class ChildClass extends MyClass {
const MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>
But $c::MY_CONST is only recognized in version 5.3.0 or later. The class I'm writing may be distributed a lot.
Basically, I have defined a constant in ChildClass and one of the functions in MyClass (father class) needs to use the constant. Any idea?

How about using static::MY_CONST?

Since php 5.3:
Use static::MY_CONST
More details on static
In this case the keyword static is a reference to the actually called class.
This illustrates the difference between static $var, static::$var and self::$var:
class Base {
const VALUE = 'base';
static function testSelf() {
// Output is always 'base', because `self::` is always class Base
return self::VALUE;
}
static function testStatic() {
// Output is variable: `static::` is a reference to the called class.
return static::VALUE;
}
}
class Child extends Base {
const VALUE = 'child';
}
echo Base::testStatic(); // output: base
echo Base::testSelf(); // output: base
echo Child::testStatic(); // output: child
echo Child::testSelf(); // output: base
Also note that the keyword static has 2 quite different meanings:
class StaticDemo {
static function demo() {
// Type 1: `static` defines a static variable.
static $Var = 'bar';
// Type 2: `static::` is a reference to the called class.
return static::VALUE;
}
}

Instead of
$c = get_class( $this );
echo $c::MY_CONST;
Do this
$c = get_class( $this );
echo constant($c . '::MY_CONST');

I couldn't get it to work with const as it prints "yonderyonder" (that's the thing about constants, they don't change), but it works fine with var:
<?php
class MyClass {
var $MY_CONST = "yonder";
public function __construct() {
echo $this->MY_CONST;
}
}
class ChildClass extends MyClass {
var $MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>

If you need to access constants, properties, methods of classes or objects you can use reflection, it provides much more details about structure of the object.
example:
class MainClass
{
const name = 'Primary';
public $foo = 'Foo Variable';
}
class ExtendedClass extends MainClass
{
const name = 'Extended';
}
/**
* From Class Name
*/
//get reflection of main class
$mainReflection = new ReflectionClass('MainClass');
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionClass('ExtendedClass');
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended
/**
* From Objects
*/
$main = new MainClass();
$extended = new ExtendedClass();
//get reflection of main class
$mainReflection = new ReflectionObject($main);
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionObject($extended);
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended

Related

override a static variable

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

Access to class variable from outside

How can I access to class variable from outside without creating new instance in PHP ? Something like this:
class foo
{
public $bar;
}
echo foo::$bar;
Is it possible or I must create method that will print or return this value and use it or create new instance ( $a = new foo; echo $a->$bar ) ?
EDIT: I don't want to create constant but classic variable that will be changed later.
make this variable static to access it with out class object.
If you wanted to change static variable value by method then you need to use static method
you can try like this:
class foo
{
public static $bar ="google";
public static function changeVal($val){
self::$bar=$val;
}
}
foo::changeVal("changed :)");
echo foo::$bar;
Output : changed :)
Demo : https://eval.in/107138
You also can changed it like this without static method:
foo::$bar = "changed";
demo : https://eval.in/107139
like this:
class foo
{
public static $bar ="google";
}
echo foo::$bar;
Output: google
demo: https://eval.in/107126
IF it makes sense to use a static variable:
class foo{
public static $bar = 'example';
}
Which could be accessed like so:
echo foo::$bar;
If the value will never change during runtime, then you probably want a class constant (http://www.php.net/oop5.constants)
class foo {
const bar = 'abc';
}
...otherwise you want a public static variable (http://www.php.net/manual/en/language.oop5.static.php)
class foo {
public static $bar = 'abc';
}
...either way, access it like this
echo foo::bar;
You can access the class variable without creating instances only when the variable is markesd as static:
class foo
{
public static $bar;
}
This is how you use a class variable:
// with instantiation
class foo {
// initialize on declare
public $bar = 1;
// or initialize in __construct()
public function __construct(){
$this->bar = 1;
}
}
$foo = new foo();
var_dump($foo->bar);
// static way
class static_foo {
public static $bar = 1;
}
var_dump(static_foo::$bar);
And this is how you instantiate a class from a random class name string variable.
$foo = new foo();
$random_class_name = $foo->bar;
try {
// following line throws if class is not found
$rc = new \ReflectionClass($random_class_name);
$obj = $rc->newInstance();
// can be used with dynamic arguments
// $obj = $rc->newInstance(...);
// $obj = $rc->newInstanceArgs(array(...));
} catch(\Exception $Ex){
$obj = null;
}
if($obj){
// you have a dynamic object
}
What's your actual question?

Change value of a variable of the parent class in the child class

class A {
protected $a;
// SOME CODE
}
class B extends A {
// SOME CODE
}
How can i edit the protected value of the variable $a inside the B class ?
I'm trying to use parent::$a = "Some Value" but doesn't work.
protected instance properties, those which where not declared using static, can be accessed in subclasses using $this :
class A {
protected $a;
// SOME CODE
}
class B extends A {
// SOME CODE
public function edit($val) {
$this->$a = $val;
echo "a is now {$this->a}\n";
}
}
call:
$b = new B();
$b->edit('foo'); // a is now foo
Refer to the manual, especially the examples.
class B extends A {
public function foo($val)
{
$this->a = $val;
}
}
quite simple :)
Remember that
Members declared protected can be accessed only within the class
itself and by inherited and parent classes
from php manual

php class extends

I want to know is it possible to have a class that's extended have a var set and used from the base class?
eg:
class me
{
public $hello = array();
protected function setter($me)
{
$this->hello[] = $me;
}
}
class foo extends me
{
public function __construct()
{
$this->setter('foo');
}
}
class yoo extends me
{
public function __construct()
{
parent::setter('yoo');
}
}
$me = new me();
$foo = new foo();
$yoo = new yoo();
print_r($me->hello);
the array printed is array() nothing is set.
Yes, you can do this by making $hello static:
public static $hello = array();
In doing so, you will have to drop the $this from $this->hello[] = $me; and replace it with a self, as hello will not longer be unique to the current object instance:
self::$hello[] = $me;
You were using
parent::setter('yoo');
But in parent class me, that function is not defined as static. So you cannot use :: to call un-static function.

PHP cannot override protected static

I can't seem to be able to override protected static variables. It's rather annoying, given that you cannot override any private variable as well. Howcan I fix that? (Have to support PHP 5.2)
<?
class Foo{
protected static $stuff = 'Foo';
public function showStuff(){
echo self::$stuff . PHP_EOL;
}
}
class Bar extends Foo{
protected static $stuff = 'Bar';
}
$f = new Foo();
$b = new Bar();
$f->showStuff(); // Output: Foo
$b->showStuff(); // Output: Foo
?>
You need to use late static bindings, a feature introduced in PHP 5.3. In your class Foo, self refers to the Foo class. You want to refer to the class where the call originated. You need to use the keyword static:
<?
class Foo{
protected static $stuff = 'Foo';
public function showStuff(){
echo static::$stuff . PHP_EOL; // <-- this line
}
}
class Bar extends Foo{
protected static $stuff = 'Bar';
}
$f = new Foo();
$b = new Bar();
$f->showStuff(); // Output: Foo
$b->showStuff(); // Output: Bar
?>
You can override them, but you cannot get the value from the parent class. Well, this is wat PHP calls overriding, while it actually reintroduces the variable and tries to hide the parent variable. That's why this won't work the way you want.
Since you're not on 5.3 yet, I think the best solution is to use (and override) a static function too. If you don't need to modify the value, you can just make the class override the function to let it return a different constant value per class. If you do need the variable, you can reintroduce both the variable and the function in each class.
class x
{
static $a = '1';
static function geta()
{
return self::$a;
}
}
class y extends x
{
static $a = '2';
static function geta()
{
return self::$a;
}
}
echo x::geta();
echo y::geta();
It is dirty, but it solves the problem until you can use the neater static:: way of PHP 5.3.
There is a better solution. You can use get_called_class() to find the current context and use that to access statics.
eg.
class Foo {
protected static $table = "foo";
static function getTable() {
$class = get_called_class();
return $class::$table;
}
}
class Bar extends Foo {
protected static $table = "bar";
}
echo Foo::getTable()."<br />\n";
echo Bar::getTable()."<br />\n";
You will get output as follows:
foo<br />
bar<br />
That will work in any PHP 5 version
Actually you can override them :)
You just can't use them in parent class, as they are static. Late static binding fixes it.

Categories