PHP: Static Readonly property in class
Asked Answered
C

5

13

My problem is: I need to overload standard get and set for static variables in class... but no such functionality provided in php... it was asked in 2008 and still not implemented... Same goes for readonly...

My question: is there a way to make a static property accesible for reading from outside, but protected from modification?

echo aaa::$qwe; //<--- echoes value of $qwe
aaa::$qwe = '666'; //<--- throws an error because variable is protected from modification

I can't use const because some variables contain arrays.

Maybe there are some workarounds?

Yeah, I know I can make it like aaa::Get('qwe') but that's no good...

Cameron answered 7/12, 2011 at 9:47 Comment(3)
Because I would need to change 2mb of existing code base, and also it's not clean, plus there are other reasons not dependent on me :)Cameron
Why not use a class constant? Or will the variable be modified internally?Covetous
Some variables store arrays and other data not allowed for const... otherwise yes, it would be the best solution.Cameron
G
5

Directly answering your question: No, you cannot mark regular properties as readonly. If you want to set primitive types (except array), that will never change, you should use constants

const QWE = '666';

That doesn't work for objects and arrays. I see two (lets say) "solutions"

  1. Use Getter

    private $qwe;
    public function getQwe() { return $this->qwe; }
    protected function setQwe($value) { $this->qwe = $value; }
    

    I don't like them very much ("Properties define the state, not the behavior, like methods do"). You always get twice as much additional methods as properties and if you have many properties, this will extremely blow up your class. However, it's as far as I can see the only way to implement what you want to achieve.

  2. Trust your users ;) Comment your property and say something like "If you change this value, probably something will break and its your very own fault".

    /**
     * QWE
     *
     * This property should be treatened as "readonly". If you change this value
     * something scary will happen to you.
     *
     * @readonly
     * @var string
     */
    public $qwe = '666';
    

    Its not great, but at least you can say "I told you".

Gherlein answered 7/12, 2011 at 10:4 Comment(5)
Only option 2 would be possible :) But leaving very important variables like that is no good :)Cameron
Trust your users...(Keep reading)!?!(wait a minute dahell I just read??!)...(Facepalm).That sir is the funiest thing I've read all day!!Promotive
@Promotive I don't know... whats the funny part? You know, that with "users" I mean other developers and not visitors of the application? And you know, that if they are "not trustworthy" they shot themself in their own foot. Nothing you have to take care about ;)Gherlein
@Gherlein NEVER TRUST ANY USER might it be the app visitor or the people that develop with your classes, There is a reason why encapsulation, Design by contract (DbC) and validation are commonly use.Promotive
@Promotive Again. This "user" is a developer, that simply use your code own their own responsibility. I am aware of design specifications, but I am also aware of the fact, that part of the contract is the documentation.Gherlein
R
3

Readonly properties were introduced in PHP 8.1, but static readonly properties are not supported.

From the RFC:

Readonly static properties are not supported. This is a technical limitation, in that it is not possible to implement readonly static properties non-intrusively. In conjunction with the questionable usefulness of readonly static properties, this is not considered worthwhile at this time.

However you can declare a static function to more or less get the same end result.

public static function getType(): string
{
    return 'Duck';
}
Redemptioner answered 9/12, 2022 at 14:0 Comment(1)
And if the value does not need to be dynamic, a class constant can do the same job.Parallelogram
U
1

If the value never changes, you can use const instead. Otherwise, there's no way that satisfies your restrictions (short of hooking function calls in PHP through an extension, but even then you'd need to change your static variable accesses to function calls; otherwise, you'd have to patch PHP).

Of course, it's highly doubtful that what your application is doing is good design. Relying on changing static properties is more or less the same as relying on global variables.

Unpeople answered 7/12, 2011 at 9:57 Comment(3)
Well, that's what I have to live with :) Existing codebase... And unfortunately I can't use const because some variables store arrays...Cameron
If the design allows such a change, you can save the arrays as CSV, or maybe JSON-encoded: const $qwe = '["666"]'Gherlein
Hm, that is actually interesting idea!Cameron
O
1

This is a bit easier:

class aaa{
private static $qwe='rty';
public static function qwe() { return self::$qwe; }
}

It does not allow changes, and is still easy to access:

aaa::$qwe = 'something'; // fails
echo aaa::qwe(); // success

I know it is not ideal, but you can do a replace all

aaa::$qwe 

with

aaa::qwe()
Olivaolivaceous answered 17/4, 2013 at 21:55 Comment(1)
Thanks Leri, fixed the first code snippet from $this->qwe; to self::$qwe. please re-rate my answer if you feel it is any better.Olivaolivaceous
C
0

It would be nice if php offered a getStatic() method but since it doesn't you can repurpose __callStatic() to fetch them like this:

class Foo
{
    private static $readonly_var = 'FOO';
    public static function __callStatic($name, $args) {
        return self::${$name};
    }
}
echo Foo::readonly_var() . PHP_EOL;

Simply call the variable name as a function. It's scalable since you don't need to create any special getter function for it to work.

Coastguardsman answered 5/12, 2023 at 19:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.