如何在 PHP 中创建最终变量?

Posted

技术标签:

【中文标题】如何在 PHP 中创建最终变量?【英文标题】:How to make a final variable in PHP? 【发布时间】:2017-05-13 21:10:28 【问题描述】:

我找不到,或者我想错了,但是我需要创建一个无法更改的变量,例如只读,例如:

final $finalVar = 'extremely secret number'; // don't change

$finalVar = 'hacked...'; // THROW I GIANT BIG ERROR HERE !

【问题讨论】:

使用常量。 secure.php.net/manual/en/language.constants.php PHP 手册说明:属性不能声明为final,只有类和方法可以声明为final。 php.net/manual/en/language.oop5.final.php @bishop 正确。对于他们的特定用例,一个常数是有效的。但如果他们着眼于更广泛的范围,那么需要注意这一点。 基本上,你需要一个常量,但你想用美元符号编写代码——这就是它的归结。解决方案非常简单——不要再写美元符号,而是使用为特定目的而存在的语言结构。 【参考方案1】:

除了常量(如 cmets 中所述)之外,我能想到的唯一方法是使用带有 private 变量的父子关系

class ParentC 
    private $var = 'bob';


class ChildC extends ParentC 
    public function setVar() 
         // Fatal error: Uncaught Error: Cannot access private property ParentC::$var
         echo parent::$var; 
    

请注意,a hacky way around that 使用反射类。但是,在大多数情况下,您不能触摸子类中的 private 父变量

【讨论】:

子类不能改变变量,也不能读取。 @Andrea 是的,但你可以创建一个 getter 方法或重载来解决这个问题【参考方案2】:

如果要创建不想更改的变量,可以使用常量:

class MyClass 

   const VERSION = '2.1'; // This constant can be view outside the class,
                          // but its value can't be changed even in this class

   function myMethod () 
       echo self::VERSION; // Inside class
   


或课外:

echo MyClass::VERSION;

功能方法:

define ('VERSION', '2.1');

echo VERSION;

【讨论】:

【参考方案3】:

虽然至少从 2012 年开始就有talk 的只读变量,甚至还有RFC 提出对象,但语言中不存在支持。

实现只读变量(或只读变量的集合,对于某些配置值可能很重要)的一种方法是使用中介容器:

class Readonly 
    public function __construct(...$vars) 
        $this->vars;
    

    public function __set($var, $value) 
        if (array_key_exists($var, $this->vars)) 
            throw new \LogicException("Variable $var is read-only");
         else 
            $this->vars[$var] = $value;
        
    

    public function __get($var) 
        return array_key_exists($var, $this->vars) ? $this->vars[$var] : null;
    

    protected $vars = [];

这允许您创建只读变量的容器:

$config = new Readonly('apikey');

$config->apikey = 'A01AB020'; // this works, first time set
echo $config->apikey;

$config->apikey = '00000000'; // boom! it's "final"

【讨论】:

我想知道,如果实际解决方案是使用常量,为什么要这么长的答案?这里没有真正的问题,OP 只是不“想要”编写没有美元符号的代码。这似乎完全是过度杀伤IMO,问题出在椅子上,而不是电脑上。 OP 应该学习使用该语言,如果他没有明确的理由不想使用为特定目的提供的构造,则不要屈从于他的意愿。我没有对此投票,但我认为这是不正确的,因为它会误导未来的访问者。 @Mjh 常量只能是标量或数组(通过 5.6+ 中的 const 或 7.0+ 中的 define)。常量会污染全局命名空间。 const 是编译时的,必须在***范围内声明:不在函数、循环或 try/catch 中。 const 不能从变量初始化,如果 OP 从配置文件中读取,这可能很重要。 (define 可以,但是我们在 @bishop 可以定义类级常量。实际的解决方案是使用常量。无论您是通过全局范围还是类别来管理它们 - 由您决定。没有必要避免常量。如果某些东西是不可变的,那么它就不是变量。如果需要保存标量以外的其他内容,那么使用 IoC 和您演示的技术是可行的方法。总有适合这项工作的工具。【参考方案4】:

使用常量:

defined('VARIABLE')  OR define('VARIABLE', 'value');

文档:definedefined

【讨论】:

【参考方案5】:

使用PHP 8.1,您现在可以将变量声明为只读:

class MyClass
    public readonly string $prop;
 
    public function __construct(string $val) 
        // Can be intialized only once.
        $this->prop = $val;
    


$myclass = new MyClass('Foo');
$myclass->prop; // Read the property
$myclass->prop = 'Bar'; // Error: Cannot modify readonly property

请注意,您只能将只读应用于类型化属性。

【讨论】:

以上是关于如何在 PHP 中创建最终变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHP Codeigniter 框架中创建错误日志 [重复]

如何在 PHP 中创建网页的图像?

如何使用 PHP 在 MySQL 中创建表?

如何在 PHP 中创建子域? [复制]

如何在纯 php 中创建刷新令牌?

如何在 DOSBox 的子程序中创建变量?