PHP trait-定义通用常量

定义一个名称空间中可能被许多类使用的常量的最佳方法是什么?我试图避免过多的继承,因此扩展基类并不是一个理想的解决方案,而且我正在努力寻找一个使用 trait 的好解决方案。这在 PHP 5.4中是否有可能,或者应该采取不同的方法?

我有以下情况:

trait Base
{
// Generic functions
}


class A
{
use Base;
}


class B
{
use Base;
}

问题是不可能在 PHP trait 中定义常量。理想情况下,我想要的东西如下:

trait Base
{
const SOME_CONST = 'someconst';
const SOME_OTHER_CONST = 'someotherconst';


// Generic functions
}

然后这些可以通过应用 trait 的类访问:

echo A::SOME_CONST;
echo B::SOME_OTHER_CONST;

但是由于特性的限制,这是不可能的。有什么想法吗?

52543 次浏览

我最终使用 用户 Sectus 的建议的接口,因为它感觉是处理这个问题最少的方法。使用一个接口来存储常量而不是 API 契约有一种不好的味道,尽管如此,也许这个问题更多的是关于面向对象设计而不是特征实现。

interface Definition
{
const SOME_CONST = 'someconst';
const SOME_OTHER_CONST = 'someotherconst';
}


trait Base
{
// Generic functions
}


class A implements Definition
{
use Base;
}


class B implements Definition
{
use Base;
}

考虑到:

A::SOME_CONST;
B::SOME_CONST;

为了限制常量的作用域,可以在命名空间中定义它们:

namespace Test;


const Foo = 123;


// generic functions or classes


echo Foo;
echo namespace\Foo;

这种方法的缺点是自动加载不适用于常量,至少不适用于5.4; 解决这个问题的典型方法是将这些常量包装在静态类中,例如:

namespace Test;


class Bar
{
const Foo = 123;
}

也可以使用静态变量。它们可以在类中使用,也可以在 trait 本身中使用。作为康斯特的替代品,我觉得挺好的。

trait myTrait {
static $someVarA = "my specific content";
static $someVarB = "my second specific content";
}


class myCustomClass {
use myTrait;


public function hello()
{
return self::$someVarA;
}
}

另一个需要考虑的问题是,是否可以使用抽象类,然后继承。

abstract class Base
{
const A = 1;
const B = 2;
}


class Class1 extends Base {}
class Class2 extends Base {}


echo Class1::A;
echo Class2::B;

当然,产生性状的部分原因是用组合代替了复杂的遗传树。

不是很好,但也许..。

trait Base
{
public static function SOME_CONST()
{
return 'value1';
}


public static function SOME_OTHER_CONST()
{
return 'value2';
}


// generic functions
}


class A
{
use Base;
}


class B
{
use Base;
}


echo A::SOME_CONST();
echo B::SOME_OTHER_CONST();

从 PHP 8.1开始,可以在 trait 中使用 readonly属性。

<?php
trait A
{
public readonly int $variable;
    

protected function initA(int $newValue){
$this->variable = $newValue;
}


public function changeVariable(int $newValue){
$this->variable = $newValue;
}
}


class B {
use A;


public function __construct() {
$this->initA(1);
}
}


$b = new B();
$b->changeVariable(5); // should faild: Fatal error: Uncaught Error: Cannot modify readonly property B::$variable

PHP 8.2会有 特质中的常量:

trait Foo {
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;
 

public function doFoo(int $flags): void {
if ($flags & self::FLAG_1) {
echo 'Got flag 1';
}
if ($flags & self::FLAG_2) {
echo 'Got flag 2';
}
if ($flags & self::FLAG_3) {
echo 'Got flag 3';
}
}
}