Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access class constant from an instance using the :: scope operator

Tags:

php

I hit a strange problem today and even as a PHP engineer i'm stumped at this:

It seems you can access a class constant from an object instance such as:

class a {
    const abc = 1;
}
$a = new a();
var_dump($a->abc);

This will output null instead of the expected 1. I was able to do the following:

class a {
    const abc = 1;
}
$a = new a();
var_dump(a::abc);

But in the context of a sub object that doesn't really know who the parent is exactly, i find it extremely annoying to do:

class a {
    const abc = 1;
}
$a = new a();
$c = get_class($a);
var_dump($c::abc);

Is it me or this is completly stupid, if not, please enlighten me why its working that way.

EDIT

Another way of doing it but it's not really better:

class a {
    const abc = 1;
}
class b {
    public function getA(){
        return new a();
    }
}
$b = new b();
$c = $b->getA();
var_dump($c::abc);

This last example works more like what i am doing and experiencing...

like image 432
Mathieu Dumoulin Avatar asked Aug 15 '12 20:08

Mathieu Dumoulin


People also ask

How to access constant in PHP class?

To access the class constant, you use the name of the class (in this case mathematics), followed by 2 colons (::), followed by the name of the constant (in this case PI). In this code, we echo out the constant, so an echo precedes this code. Usually by convention, constants are put in all uppercase.

How do you call a class constant?

There are two ways to access class constants. Inside the class: The self keyword and Scope Resolution Operator ( :: ) is used to access class constants from the methods in a class. Outside the class: The class name and constant name is used to access a class constant from outside a class.


1 Answers

I found a relatively nice and clean way to make my problem easier to live with. Here is the solution i've applied. It is not necessarely the best but for my uses it does exactly what i need.

By creating a magic __get method, i intercept the request for the constant name from and instance point of view and i use a quick reflection to see if that constant exists and return it's value.

This allows me to actually use all in one line a pattern that looks like this:

class a {
    const abc = 1;
    public function __get($key){
        $r = new ReflectionObject($this);
        if($r->hasConstant($key)){ return $r->getConstant($key); }
    }
}
class b {
    public function getA(){
        return new a();
    }
}
$b = new b();
var_dump($b->getA()->abc);
var_dump($b->getA()->def);

Althought i'd have liked to do:

var_dump($b->getA()::abc);
var_dump($b->getA()::def);

I guess this could be possible later in 5.4+ considering we finaly have array dereferencing, we could probably ask them to add static dereferencing soon.

like image 173
Mathieu Dumoulin Avatar answered Oct 03 '22 10:10

Mathieu Dumoulin