PHP Traits - 定义通用常量

Tom*_*itt 53 php oop traits

定义名称空间中许多类可能使用的常量的最佳方法是什么?我试图避免过多的继承,因此扩展基类不是一个理想的解决方案,我很难找到一个使用特征的好解决方案.这在PHP 5.4中是否可能以任何方式实现,还是应采取不同的方法?

我有以下情况:

trait Base
{
    // Generic functions
}

class A 
{
    use Base;
}

class B 
{
    use Base;
}
Run Code Online (Sandbox Code Playgroud)

问题是无法在PHP特征中定义常量.理想情况下我想要的是以下内容:

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

    // Generic functions
}
Run Code Online (Sandbox Code Playgroud)

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

echo A::SOME_CONST;
echo B::SOME_OTHER_CONST;
Run Code Online (Sandbox Code Playgroud)

但由于性状的限制,这是不可能的.有任何想法吗?谢谢.

Tom*_*itt 74

我最终使用@sectus建议的接口,因为它感觉是处理这个问题最不成问题的方式.使用一个接口来存储常量而不是API契约有一个难闻的气味,尽管如此可能这个问题更多的是关于OO设计而不是特征实现.我对这个解决方案仍然不是很满意所以如果有人提出更好的建议,我会暂时不接受答案.

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;
}
Run Code Online (Sandbox Code Playgroud)

这允许:

A::SOME_CONST;
B::SOME_CONST;
Run Code Online (Sandbox Code Playgroud)

  • 所以接口可以有常量......但是特性不能?PHP变得更奇怪,更奇怪. (64认同)
  • @Adambean重写常量会破坏`常量'的目的,它并不意味着改变. (5认同)
  • @Aknosis 我个人认为它不仅仅是一个常数在其生命周期中不会改变价值。这并不意味着在扩展类时不能用另一个值重新定义它(并使用 [eg] `static::VALIDATION_REGEX` 来获取 [late-static-bound](https://secure.php.net/手册/en/language.oop5.late-static-bindings.php) 值) (5认同)
  • PHP“错误”[#75060](https://bugs.php.net/bug.php?id=75060) (2认同)

Mic*_*ael 26

您也可以使用静态变量.它们可以在类或特征本身中使用. - 作为const的替代品,我可以正常工作.

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

class myCustomClass {
    use myTrait;

    public function hello()
    {
        return self::$someVarA;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道这是旧的,但是你不想使用const来改变它的值吗? (12认同)
  • 您不能在 Trait 中使用常量。 (2认同)

Iva*_*ych 14

PHP 8.2(2022 年 12 月)在 Traits 1中有常量。引用PHP 手册

从 PHP 8.2.0 开始,特征还可以定义常量。

示例 #14 定义常量进行比较并查看示例:

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';
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. PHP 8.2新特性:特征中的常量RFCCHANGE


Ja͢*_*͢ck 9

要限制常量的范围,可以在命名空间内定义它们:

namespace Test;

const Foo = 123;

// generic functions or classes

echo Foo;
echo namespace\Foo;
Run Code Online (Sandbox Code Playgroud)

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

namespace Test;

class Bar
{
    const Foo = 123;
}
Run Code Online (Sandbox Code Playgroud)


Jek*_*kis 5

不是一个好人,但也许...

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();
Run Code Online (Sandbox Code Playgroud)

  • @John Hunt,“final”不适用于特征,请参阅/sf/answers/2343705801/ (2认同)