php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #75060 Allow traits to have constants to support emerging use cases
Submitted: 2017-08-10 18:43 UTC Modified: 2022-12-14 14:07 UTC
Votes:49
Avg. Score:4.2 ± 1.1
Reproduced:45 of 47 (95.7%)
Same Version:13 (28.9%)
Same OS:28 (62.2%)
From: jocrutrisi at ibsats dot com Assigned: cmb (profile)
Status: Closed Package: Class/Object related
PHP Version: 7.2.0beta2 OS: All
Private report: No CVE-ID: None
 [2017-08-10 18:43 UTC] jocrutrisi at ibsats dot com
Description:
------------
I want to preface this with a disclaimer that I'm aware that "traits" in other languages are even more conservative than PHP is - they don't allow properties, while PHP does.

But what we have in PHP is still a useful variation of traits, called "mixins". A mixin is a slice of a class that has properties, methods, constants and so it can contain everything needed for implementing a standalone "slice" of functionality for reuse in classes.

But while PHP allows properties, it doesn't allow constants in traits. The reasons for this decision are unclear.

After traits were introduced in PHP 5.4, we've seen the roles, purpose and use scenarios for constants increasingly grow over time:

1. PHP 5.6 allowed for array constants, which made constants handy for constant look-up maps etc.
2. PHP 7.0 introduced opcache as a built-in feature, and it places constants in shared memory, which makes them especially performant for big look-up maps.
3. PHP 7.1 introduced private/protected constants, which means constants can now be used as an internal implementation detail, and not necessarily a public constant that can be specified in a separate class or interface.

Unfortunately traits still don't allow constants... it's easy to see use cases for them, here's a very basic example:

trait ColorTrait {
    protected $color;
    protected const COLORS = [
        'red' => true, 
        'green' => true, 
        'blue' => true
    ]; 
    function setColor($color) {
        if (!isset(self::COLORS[$color])) {
            throw new Exception('Meh');
        }
        $this->color = $color; 
    }
}

Note, I'm aware of a duplicate of this bug: #70986, but since it's from 2 years ago I wanted to make a better case for the feature, in light of PHP 7.1's improvement on constants.

The problem raised in the original bug report is: what happens if different constants of the same name are in different traits? 

I propose an easy to implement conservative solution:
Fatal Error "Cannot use traits with the same constant names".

We can always refine the solution now, and reduce the surface of rejected trait combinations later on, but to at least support the basic use cases, which now we're also denied.



Test script:
---------------
trait Foo {
    const BAR = 123;
}

Expected result:
----------------
No errors.

Actual result:
--------------
Fatal error: Traits cannot have constants

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-08-11 11:16 UTC] cmb@php.net
-Status: Open +Status: Suspended
 [2017-08-11 11:16 UTC] cmb@php.net
Thank you for your interest in PHP and for submitting a feature
request. Please be aware that due to the magnitude of change this
request requires, it would be necessary to discuss it on PHP
Internals list (internals@lists.php.net) as an RFC. Please read
the guide about creating RFCs here:
<https://wiki.php.net/rfc/howto>. If you haven't had experience
with writing RFCs before, it is advised to seek guidance on the
Internals list (<http://php.net/mailing-lists.php>) and/or solicit
help from one of the experienced developers. 

Please do not consider this comment as a negative view on the
merits of your proposal – every proposal which requires changes of
certain magnitude, even the very successful and widely supported
ones, must be done through the RFC process. This helps make the
process predictable, transparent and accessible to all developers.
 [2020-06-21 01:10 UTC] jake at qzdesign dot co dot uk
Can this please be considered for inclusion in PHP 8.0?  There is still time.

The specific limitation seems to be unfounded and impedes good OO design (where multiple inheritance is not available, by language design, and traits provide and enforce a clearer design pattern).

The following comment on [Stack Overflow](https://stackoverflow.com/questions/24357985/php-traits-defining-generic-constants#comment-49583022) has received 73 upvotes, the most I've ever seen for a SO comment:

> So interfaces can have constants...but traits can't? PHP gets weirder and weirder.

Clearly there is strong demand for this issue to be addressed.
 [2022-12-14 14:07 UTC] cmb@php.net
-Status: Suspended +Status: Closed -Assigned To: +Assigned To: cmb
 [2022-12-14 14:07 UTC] cmb@php.net
Constants in traits are available as of PHP 8.2.0[1].

[1] <https://wiki.php.net/rfc/constants_in_traits>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC