Php traits and constants

PHP 8.2 is released with read-only classes, new stand-alone types, trait constants, and more

The PHP team has released PHP 8.2 today with read-only classes, new stand-alone types, a new random extension, trait constants, and more:

Readonly classes

Building on PHP 8.1’s read-only properties, marking a class as read-only makes every property on a class read-only and prevents the creation of dynamic properties.

readonly class BlogData
public string $title;
public Status $status;
public function __construct(string $title, Status $status)
$this->title = $title;
$this->status = $status;
>
>

Disjunctive normal form types (DNF)

DNF types combine union and intersection types :

class Foo
public function bar((A&B)|null $entity)
if ($entity === null)
return null;
>
return $entity;
>
>

Null, false, and true stand-alone types

PHP 8.2 now allows false , true , and null as standalone types. This example is pretty self-explanatory:

class Falsy
public function alwaysFalse(): false /* . */ *>
public function alwaysTrue(): true /* . */ *>
public function alwaysNull(): null /* . */ *>
>

Constants in traits

Constants are now allowed in traits. You cannot access constants through the name of the trait, however, you can access the constant through the class using the trait:

trait Foo
public const CONSTANT = 1;
public function bar(): int
return self::CONSTANT; // Fatal error
>
>
class Bar
use Foo;
>
var_dump(Bar::CONSTANT); // 1

Dynamic property deprecation

Dynamic properties is deprecated, meaning that you will get a deprecation notice when assigning a value to dynamic property:

class User
public $name;
>
$user = new User();
$user->last_name = 'Doe'; // Deprecated notice
$user = new stdClass();
$user->last_name = 'Doe'; // Still allowed

You also have the option to allow dynamic properties using the AllowDynamicProperties attribute:

#[AllowDynamicProperties]
class User() <>
$user = new User();
$user->foo = 'bar';

New classes, interfaces, attributes, and functions

PHP 8.2 contains new classes, interfaces, attributes, and functions. For the complete list, check out the New Classes, Interfaces, and Functions section of the PHP 8.2.0 Release Announcement.

We’ve already mentioned the AllowDynamicProperties attribute. Another attribute is the #[\SensitiveParameter] attribute, which redacts sensitive information within a stack trace:

function sensitiveParametersWithAttribute(
#[\SensitiveParameter]
string $secret,
string $normal
)
throw new Exception('Error!');
>

Learn more

To get up to speed on these new features, check out the PHP 8.2.0 Release Announcement page for examples before/after PHP 8.2, and view these links for more details on each item:

Full stack web developer. Author of Lumen Programming Guide and Docker for PHP Developers.

Источник

PHP 8.2: Constants are supported in traits

PHP Traits provide a mechanism to reuse code in PHP classes and Enums without using class inheritance chains, interfaces, or abstract classes. Traits are similar to PHP classes, in that they both PHP classes and traits support properties, methods, autoloading, magic constants, and other PHP class semantics.

Traits are meant to be used by PHP classes. When a trait is used in a PHP class, all the methods and properties declared in the trait are available within the PHP class.

However, prior to PHP 8.2, it was not possible to declare constants in PHP traits. Attempting to declare a constant in a Trait resulted in a fatal error at the compile time.

Fatal error: Traits cannot have constants in . code on line . 

Although traits were not allowed to declare constants, it was possible to access constants in PHP classes that the traits are used in. This resulted in incomplete leaking implementations because there was no way for the trait to ensure the classes that use the trait declare the referenced constants, and there was no way to programmatically enforce it.

The VersionDependent declared above assumes that the classes that use VersionDependent trait will declare CURRENT_VERSION and MIN_VERSION constants, but there is no way for the VersionDependent trait to ensure those constants are declared.

Since PHP 8.2, declaring constants in traits is supported. Trait constants can also be declared with visibility modifiers and as final (since PHP 8.1). All of the following constant declarations are valid in PHP 8.2 and later:

trait FooBar < const FOO = 'foo'; private const BAR = 'bar'; final const BAZ = 'baz'; final protected const QUX = 'qux'; >class Test < use FooBar; >echo Test::BAZ; // 'bar'

It is not mandatory for the composing class to declare the constants declared in the trait. However, the constants declared in the compositing class must be compatible with the constants declared in the trait.

Overriding Trait Constants

Overriding is not allowed in directly composed classes

Composing a PHP class with same name, visibility, and value as the constants declared in the trait is allowed:

trait FooBar < const FOO = 'foo'; private const BAR = 'bar'; final const BAZ = 'baz'; final protected const QUX = 'qux'; >class ComposingClass

All four constants declared in the ComposingClass are considered compatible with the FooBar trait because all of them have exact the same visibility, final flag, and most importantly, the value.

If the composing class declares an incompatible constant, PHP throws a fatal error at compile-time:

trait FooBar < const FOO = 'foo'; private const BAR = 'bar'; final const BAZ = 'baz'; final protected const QUX = 'qux'; >class ComposingClass < use FooBar; const FOO = 'zzz'; // Value is different. protected const BAR = 'bar'; // Visibility is different const BAZ = 'baz'; // Final flag is removed >
Fatal error: ComposingClass and FooBar define the same constant (FOO) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in . on line . Fatal error: ComposingClass and FooBar define the same constant (BAR) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in . on line . Fatal error: ComposingClass and FooBar define the same constant (BAZ) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in . on line . 

Overriding is allowed on derived classes

Classes that extend a composing class can override the constants if the constant is not declared final :

trait VersionDependent < protected const CURRENT_VERSION = '2.6'; protected const MIN_VERSION = '2.5'; protected function ensureVersion(): void < if (self::CURRENT_VERSION < self::MIN_VERSION) < throw new Exception('Current version is too old'); >> > class Application < use VersionDependent; >class MockApplication extends Application

All of the constants declared in the snippet above are valid, and allowed since PHP 8.2.

Overriding is not allowed for final constants

If the constant in the trait is declared with the final flag, attempting to override it results in a fatal error:

trait Test < final protected const FOO = 'foo'; >class BaseContainer < use Test; >class ApplicationContainer extends BaseContainer
Fatal error: ApplicationContainer::FOO cannot override final constant BaseContainer::FOO in . on line . 

Directly accessing trait constants is not allowed

PHP traits are meant to be used with classes and Enums, and thus, directly accessing constants is not allowed. The following snippet results in an Error

trait Test < public const FOO = 'foo'; >echo Test::FOO; constant('Test::FOO');
Error: Cannot access trait constant Test::FOO directly in . 6

Further, the defined function that returns whether a constant exists returns false when a trait constant is passed:

Trait Conflicts

When a class is composed with multiple traits that declare the same constants, both declarations must match the value, visibility, and the final flag.

trait Foo < final protected const ALPHA = 1; >trait Bar < final protected const ALPHA = 1; >class Test

Although both Foo and Bar traits declare an ALPHA constant, composing the Test class is allowed because both traits declare the constant with exact same values, visibility, and finality.

Attempting to composer a class with mismatching constant declarations result in a compile-time fatal error:

trait Foo < protected const ALPHA = 1; protected const BETA = 1; protected const GAMMA = 1; >trait Bar < protected const ALPHA = 2; // Different value public const BETA = 1; // Different visibility final protected const GAMMA = 1; // Different finality >class Test
Fatal error: Foo and Bar define the same constant (ALPHA) in the composition of Test. However, the definition differs and is considered incompatible. Class was composed in . on line . Fatal error: Foo and Bar define the same constant (BETA) in the composition of Test. However, the definition differs and is considered incompatible. Class was composed in . on line . Fatal error: Foo and Bar define the same constant (GAMMA) in the composition of Test. However, the definition differs and is considered incompatible. Class was composed in . on line . 

Backwards Compatibility Impact

PHP versions prior to PHP 8.2 did not allow declaring constants in traits, and existing applications should not cause any issues in PHP 8.2. However, applications that declare constants in traits will not work in older PHP versions, and result in a fatal error in PHP 8.1 and older versions:

Fatal error: Traits cannot have constants in . code on line . 

There is no way to back-port this feature to older PHP versions.

Источник

Читайте также:  Python get object properties
Оцените статью