Why Doesn't PHP Permit Private Const

Why doesn't PHP permit private const?

Use private static properties.

In that case you will have the same variable throughout all objects and if you want to extend its scope to nested, you can expose a getter method to get its value and restrict variables settings.

Are private constants possible in PHP?

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

php class constant visibility

As of PHP7.1 visibility modifiers are allowed for class constants, in previous versions it's not possible to set the visibility of constants in a class. They're always public. See the comments at http://www.php.net/manual/en/language.oop5.constants.php for more information.

PHP - why I couldn't declare static const variable?

Your code should be:

class Types{
const car = "CarClass";
const tree = "TreeClass";
const cat = "CatClass";
const deathstar = "DeathStarClass";
}

Note that since constants are tied to the class definition, they are static by definition.

From Docs:

As of PHP 5.3.0, it's possible to
reference the class using a variable.
The variable's value can not be a
keyword (e.g. self, parent and
static).

http://www.php.net/manual/en/language.oop5.static.php

More Info:

http://php.net/manual/en/language.oop5.constants.php

Why would you private encapsulate a private constant?

The reason for private_constant is to prevent other code from accessing the constant directly.

some_constant might return the constant today, but it's not obligated to do that. If programming-by-contract then it's obligated to return a hash in that form, the origin of which is irrelevant.

For example, you have that code today, but what about tomorrow it evolves to:

class Foo < Bar
SM_CONSTANT = {
a: { name: 'A', priority: 2 },
b: { name: 'B', priority: -1 }
}.freeze
private_constant :SM_CONSTANT

private
def some_constant
SM_CONSTANT.map { |k,o| [ k.to_s, o[:name] ] }.to_h
end
end

Where the internals have completely changed but to outside code nothing has, the same calls produce the same results. This is why encapsulation is important. It gives you the freedom to iterate and rework code within a particular context without concerning yourself about breaking other things.

If code accessed SM_CONSTANT directly it'd have to be re-written to accept this new structure.

Pros and Cons of Interface constants

Well, I think that it boils down to the difference between good and good enough.

While in most cases you can avoid the use of constants by implementing other patterns (strategy or perhaps flyweight), there is something to be said for not needing a half dozen other classes to represent a concept. I think what it boils down to, is how likely is there a need for other constants. In other words, is there a need to extend the ENUM provided by the constants on the interface. If you can foresee needing to expand it, then go with a more formal pattern. If not, then it may suffice (it'll be good enough, and hence be less code to write and test). Here's an example of a good enough and a bad use:

Bad:

interface User {
const TYPE_ADMINISTRATOR = 1;
const TYPE_USER = 2;
const TYPE_GUEST = 3;
}

Good Enough:

interface HTTPRequest_1_1 {
const TYPE_CONNECT = 'connect';
const TYPE_DELETE = 'delete';
const TYPE_GET = 'get';
const TYPE_HEAD = 'head';
const TYPE_OPTIONS = 'options';
const TYPE_POST = 'post';
const TYPE_PUT = 'put';

public function getType();
}

Now, the reason that I chose those examples is simple. The User interface is defining an enum of user types. This is very likely to expand over time and would be better suited by another pattern. But the HTTPRequest_1_1 is a decent use-case, since the enum is defined by RFC2616 and will not change for the lifetime of the class.

In general, I don't see the problem with constants and class constants as being a global problem. I see it as a dependency problem. It's a narrow distinction, but a definite one. I see global problems as in global variables which are not enforced, and as such create a soft global dependency. But a hard-coded class creates an enforced dependency, and as such create a hard global dependency. So both are dependencies. But I consider the global to be far worse since it's not enforced... Which is why I don't like to lump class dependencies with global dependencies under the same banner...

If you write MyClass::FOO, you're hard-coded to the implementation details of MyClass. This creates a hard-coupling, which makes your code less flexible, and as such should be avoided. However, interfaces exist to permit exactly this type of coupling. Therefore MyInterface::FOO doesn't introduce any concrete coupling. With that said, I wouldn't introduce an interface just to add a constant to it.

So if you're using interfaces, and you're very sure that you (or anyone else for that matter) won't need additional values, then I don't really see a huge issue with the interface constants... The best designs wouldn't include any constants or conditionals or magic-numbers or magic-strings or hard-coded anything. However, that adds additional time to the development, as you must consider the uses. My view is that most times it's absolutely worth taking the additional time to build a great solid design. But there are times when good enough really is acceptable (and it takes an experienced developer to understand the difference), and in those cases it's fine.

Again, that's just my view on it...

Is it possible to reference from one static variable to another (within classes)?

Starting form php 5.6 you can do like this:

class EmployeeDAO
{
const FIND_ALL = 'SELECT * FROM employee';

const FIND_BY_NAME = self::FIND_ALL .
' WHERE employee.name LIKE :name';
}

Constant in PHP class and static keyword

You have to add the static keyword to the constant used as default value.

public static function alert($title, $type=static::ALERT_ERROR) {
// ....
}

But static is only determined at runtime. So if static behaviour is really needed then:

public static function alert($title, $type=null) {
if ($type === null) {
$type = static::ALERT_ERROR;
}
// ...
}

If static is not really necessary then replace all static:: as self::

   public static function alert($title, $type=self::ALERT_ERROR) {        
switch ($type){
default:
case self::ALERT_ERROR:
$class="alert-danger"; break;
case self::ALERT_WARN:
$class="alert-warning"; break;
case self::ALERT_INFO:
$class="alert-info"; break;
}
....
}


Related Topics



Leave a reply



Submit