如何在类构造函数中定义常量?

时间:2011-08-22 09:04:47

标签: php class constants

我可以在类构造函数中定义一个类常量吗?

(基于某些条件)

6 个答案:

答案 0 :(得分:10)

这违背了类常量的想法 - 它们不应该依赖于特定的实例。你应该改用变量。

但是,如果您坚持这样做,非常冒险并且可以安装PHP扩展,您可以查看允许在运行时修改类及其常量的runkit扩展。请参阅此文档:http://www.php.net/manual/en/function.runkit-constant-add.php

答案 1 :(得分:3)

我认为你不能。

它也没有意义 - 类常量可以在静态上下文中使用,其中首先没有构造函数。

你必须使用一个变量 - 这就是他们的目的。

答案 2 :(得分:1)

答案 3 :(得分:1)

就标准实例构造函数而言,这是没有办法的,正如其他人指出的那样,这是没有意义的。这些构造函数在创建时就针对每个创建的对象实例进行调用。无法保证在某些代码尝试访问该常量之前会调用此构造函数。这也没有意义,因为每次构造新实例时,都会一遍又一遍地调用代码,而const只能设置一次。

如果PHP提供某种静态构造函数,让您一次为未初始化的常量设置值,或者在定义常量时允许更多类型的表达式,那将是很好的。但是这些不是PHP当前的功能。在2015年,RFC提出了建议添加静态类构造函数的建议,但在我撰写此答案时,它仍处于草案状态,自2017年以来未进行任何修改。

我认为目前最好的选择是在这种情况下不要使用常量,而应使用返回所需值的静态方法。这非常简单,因为它仅按原样使用PHP语言功能(不需要任何特殊扩展名),可以以标准方式调用这些静态方法,并且您无需破解自动加载过程即可调用某种设置静态变量的初始化函数。该方法可能需要依赖私有静态变量,以确保每次返回对象实例时都返回相同的实例。您将需要将此方法的实现编写为常量,就像它将始终返回同一件事一样,但是要利用能够执行常量无法完成的事情,例如在对象实例上返回或依赖复杂的表达式或函数调用。这是一个示例:

final class User
{
    /** @var DefinitelyPositiveInt|null */ private static $usernameMaxLength;
    public static function getUsernameMaxLengthConst(): DefinitelyPositiveInt
    {
        if ($usernameMaxLength === null) {
            $usernameMaxLength = new DefinitelyPositiveInt(40);
        }
        return $usernameMaxLength;
    }
}

$usernameInput.maxLength = User::getUsernameMaxLengthConst();

这仍然不是一个完美的解决方案,因为它依赖于程序员在需要时以类似常量的方式编写它们(总是返回相同的值)。另外,我不喜欢在方法名称中记录它是const的事实的最佳位置,因此调用它的时间更长。我也不喜欢您现在必须将其作为方法来调用,而不仅仅是访问属性,这在语法上会更好。

此示例本质上是单例的实现,但是有时单例的目的是成为一个常量,而不仅仅是单例。我的意思是,您可能希望实例始终存在,并且它可能是不可变的类型(所有属性都不是公共的或可变的,只有具有返回新对象/值的方法)。

答案 4 :(得分:0)

很抱歉将它破解给您,但是在普通PHP中无法实现。 我对框架或扩展不是很确定,但是我确定在香草PHP中是不可能的。 我建议您改用变量。

答案 5 :(得分:0)

您仍然不能,但是也许其中一些(渐进奇怪的)想法(只是想法,而不是真正的解决方案)对您有用:

(1)您可以使用私有属性公共获取器方法。该属性不能在类外部进行修改,例如常量,但不幸的是,它是作为方法而不是常量来访问的,因此语法不相同。

class aClass{
  private $const;
  function __construct($const){
    $this->const=$const;      
  }
  function const(){
    return $this->const;
  }
}
    
$var1=new aClass(1);
echo $var1->const(); //Prints 1

(2)如果您确实希望从外部以常量访问此值,则您可以在构造函数 中使用define ()。不幸的是,它并没有与类或对象名绑定(就像在使用 const 时使用的那样,例如使用myClass::myConst)。此外,它仅在您创建类的单个实例时才有效。您创建的第二个对象将因为未绑定而抛出错误以重新定义常量。

class otherClass{  
  function __construct($const){
    define('_CONST',$const);
  }
  function const(){
    return _CONST;
  }
}

$var2=new otherClass('2');
echo $var2->const(); //Prints 2
echo _CONST; //Prints 2

@$var3=new aClass('3'); //Notice: Constant _CONST already defined
echo _CONST; //Still prints 2!

(3)也许最后一个问题可以通过为变量名赋予常量来解决,这些常量与它们所属的对象有关。这可能有点怪异……但也许对某人有用。

class onemoreClass{
  private $name;
  function __construct($const,$name){
    $this->name=$name;
    $constname=$this->name."_CONST";
    define($constname,$const);    
  }
  function const(){
    return constant($this->name.'_CONST');
  }
}

$name='var4';
$$name=new onemoreClass(4,$name);

echo $var4->const(); //Prints 4
echo var4_CONST; //Prints 4

$name='var5';
$$name=new onemoreClass(5,$name);

echo $var5->const(); //Prints 5
echo var5_CONST; //Prints 5
相关问题