Home » Php » php – Cannot access class constant from an instance using the :: scope operator

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

Posted by: admin July 12, 2020 Leave a comment

Questions:

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…

How to&Answers:

Just use the instance variable with the scope resolution operator:

$a = new a();
var_dump($a::abc);

This prints 1.

Answer:

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.

Answer:

The PHP documentation indicates that class constants are accessed via SRO (::) rather than ->.

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

Answer:

ike I mentioned, in php constants are tied to the class definition, they are static by definition and cannot be accessed using the -> operator.

If you really want to use it with your coding paradigm, you can try the reflection class in php5.

class MyClass
{
   const A = "I am A";
}

$o = new ReflectionClass( "MyClass" );
echo $o->getconstant("A"); //will print "I am A"

Also, I think the example in your EDIT might not work..I did not run it, but I am not sure if the SRO(::) can be invoked on anything that is not a class reference..

Answer:

I know this is an old thread, but for people who want to know the best way to do this have a look at the PHP function constant().

With constant() you can simply do this:

$a = new a();
$value = constant(get_class($a)."::abc");
// $value === 1

this has been available since PHP 4, and still works perfectly in PHP 5.5

Answer:

When trying to use const defined in a class inside a different namespace, the Scope Resolution Operator (::) can be used without problems as stated by the docs prefixing the namespace before the class in which the const was declared with this format:

  • (<namespace>"\")*<className>::<const>

With the next namespace, class and const definitions:

models/OperationModel.php

<?php
namespace models;

class OperationModel {
  const OPERATION_INITIALIZING = 1;
}

You can use the const from another namespace\class like this:

controllers/MobileController.php

<?php
namespace controllers;

use models\OpertionModel;

class MobileController {
  private function thingy() {
    $operation_status = models\OperationModel::OPERATION_INITIALIZING;
  }
}