74

PHP does not allow

class Foo
{
    private const my_private_const;

but of course allows

const my_const;

So in effect constants are global because I can access my_const anywhere using Foo::my_const

Is there a way to make private constants?

Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
  • 8
    if it's a constant value, would it matter if its private or not? – hjpotter92 Apr 19 '12 at 16:22
  • you can define class constants that belong to a class http://www.php.net/manual/en/language.oop5.constants.php – Hajo Apr 19 '12 at 16:23
  • @Hajo - how? private const produces an error. –  Apr 19 '12 at 16:24
  • @Hajo: Incorrect. As TheAllFoo mentioned, a constant can be referred to anywhere using `Class::CONSTANT`. – Mike Purcell Apr 19 '12 at 16:25
  • @TheAllFoo seems class constants are not changeable from public to something else, sorry – Hajo Apr 19 '12 at 16:25
  • Where is the dependency injection advocate when you need one? –  Apr 19 '12 at 16:26
  • i wonder why a private or proctected attribute / property is not usable in his case – Hajo Apr 19 '12 at 16:29
  • I wanted to do it for consistencies ( this is how I do it in javaScript ) sake and for the sake of encapsulation and dependency injection as good programming practice, i.e. I wanted to inject my globals, not just access them –  Apr 19 '12 at 16:32
  • @ChasingDeath: It matters: you don't want to expose publicly a constant used only by internal (private or protected) members. – netcoder Apr 19 '12 at 16:42
  • @Hajo: Properties can be modified. They are also very different from the Zend Engine standpoint: they are stored in totally different symbol tables, with constants being stored in a (somewhat) read-only area of memory. Also, constants can be retrieved using a single opcode while properties require at least two. – netcoder Apr 19 '12 at 17:22
  • It might be useful to have private constants when generating doxygen documentation (that is, when you're telling doxygen not to expose private class members). – Marcello Romani Oct 10 '13 at 07:30
  • can't you just define a constant in a private method and give it out – Thielicious Sep 04 '16 at 13:14
  • 7
    Now its possible in PHP 7.1.0 (http://php.net/archive/2016.php#id2016-12-01-3) – Tahir Yasin Dec 02 '16 at 13:24

4 Answers4

153

Folks! PHP 7.1.0 has been released

Now it's possible to have visibility modifiers with class constants.

<?php
class Foo {
    // As of PHP 7.1.0
    public const BAR = 'bar';
    private const BAZ = 'baz';
}
echo Foo::BAR, PHP_EOL;
echo Foo::BAZ, PHP_EOL;
?>

Output of the above example in PHP 7.1:

bar

Fatal error: Uncaught Error: Cannot access private const Foo::BAZ in …
Tahir Yasin
  • 11,489
  • 5
  • 42
  • 59
44

The answer is a simple "no". PHP doesn't support this concept. The best you can do is a private static variable in the class, which isn't as good of course because it's not readonly. But you just have to work around it.

Edit

Your question got me thinking - here's something I've never tried, but might work. Put another way "this is untested". But say you wanted a "private constant" called FOO:

// "Constant" definitions
private function __get($constName){
    // Null for non-defined "constants"
    $val = null;

    switch($constName){
        case 'FOO':
            $val = 'MY CONSTANT UNCHANGEABLE VALUE';
            break;
        case 'BAR':
            $val = 'MY OTHER CONSTANT VALUE';
            break;
    }

    return $val;
}

Of course your syntax would look a bit odd:

// Retrieve the "constant"
$foo = $this->FOO;

...but at least this wouldn't work:

$this->FOO = 'illegal!';

Maybe something worth trying?

Cheers

Madbreaks
  • 19,094
  • 7
  • 58
  • 72
  • 1
    This is an awesome suggestion... I will most definitely use it! Thanks for sharing. Another option is to make all variables private and protected, then create a function like this one to filter which variables can be changed and which are forced to be read-only.. See this I just published! http://www.designersgate.com/blogs/?p=187 – raphie Dec 20 '12 at 18:41
  • 1
    Unfortunately the magic private getter won't work as PHP wants __get with public visibility. – marcosdsanchez Nov 20 '14 at 18:06
  • Basically the concept of "runtime defined constants". The implemetation is a cool idea. I like it. And `$this->FOO` is not odd, if PHP would support "constants as variables" like Java - then it would be the proper OOP access to a class constant. – Jens A. Koch Jan 04 '15 at 03:34
  • I modified your code a bit, added final to class and blocked modification by using magic set. see http://3v4l.org/UgEEm – Jens A. Koch Jan 04 '15 at 03:43
  • @Jens-AndréKoch Glad you like. The addition of preventing setting using `__set` is a great one, please feel free to add it to the answer if you feel so inclined. – Madbreaks Jan 06 '15 at 00:13
  • @Madbreaks, is marcosdsanchez's comment true? – Robert Pounder Nov 17 '15 at 13:35
  • the private and private static function approach: private static function cX() { return "x"; } does not work in the context: private static $mapper = array(self::cX() => "abc123",....); however the following does work: const cX = "x"; private static $mapper = array(self::cX => "abc123",....); ...so there really is no equivalent substitute for private constants. Bring on PHP 7.1! – Pancho Aug 06 '16 at 09:35
32

Note, that visibility modifiers for class constants have been added in PHP 7.1.

RFC: Support Class Constant Visibility

Invis1ble
  • 1,295
  • 2
  • 17
  • 35
7

A simplified version of @Madbreaks' workaround: write a private static function that returns the value of your private "constant":

private static function MY_CONSTANT() {
    return "constant string";
}

Usage:

public static function DoStuff() {
    echo self::MY_CONSTANT();
}
alexanderbird
  • 3,847
  • 1
  • 26
  • 35