3

I'm trying to use classes with static methods and properties instead of Singletons. Everything was ok until I had to unset a static property, and my PHP 8.0 threw an error. I need this because the property may not be set at some point, for lazy loading or state reset.

Check this example code:

<?php
declare(strict_types=1);

final class
    TextContainer
{

    private static string $text;

    public static function has():bool
    {
        return isset(self::$text);
    }

    public static function getAfterHas():string
    {
        return self::$text;
    }

    public static function set(string $v):void
    {
        self::$text = $v;
    }

    public static function unset():void
    {
        unset(self::$text);
    }

}

TextContainer::set('foo');

if (TextContainer::has())
{
    echo TextContainer::getAfterHas();
}

TextContainer::unset();

if (TextContainer::has())
{
    echo TextContainer::getAfterHas();
}

The error message it shows is: Fatal error: Uncaught Error: Attempt to unset static property TextContainer::$text.

I would prefer not using some kind of workaround like assigning null to the property, because I like the strong typing, and that would force me to type hint the property as string|null.

Any ideas? Thank you in advance.

Joan Botella
  • 315
  • 1
  • 2
  • 14
  • it does seem to work if you use type `array`, have a [look](https://3v4l.org/8iohS) – berend Jan 04 '21 at 14:27
  • 4
    Unsetting the actual static property seems like quite a strange requirement - at that point you're changing the fundamental structure of your class. In my head, it would be akin to removing an entire method. You talk about "resetting" your state - in that case, you *should* just be setting the value to null, since that's closer to how it is when the class first loads. You can type-hint the value as `?string` if that makes your code a bit cleaner than `string|null`. – iainn Jan 04 '21 at 14:36
  • 1
    @iainn Certainly, the [solution with ?string](https://3v4l.org/kooZM) is not that dirty, but I don't see the unset as "changing the fundamental structure" of the class. It is more like "de-initializing" the property. I have done that many times before on [non static classes](https://3v4l.org/SeORZ), and I think it is cleaner than allowing the null value in a property. – Joan Botella Jan 04 '21 at 15:22
  • @berend I have also though about doing somethink like that, but i think it is dirtier than the ?string solution. And the type hinting suffers from doing so. – Joan Botella Jan 04 '21 at 15:25
  • I can see arguments for both ideas/solutions but I agree with @JoanBotella about being able to "de-initialize" a property using `unset`. I too think it is cleaner. – Dave Jan 04 '21 at 15:25
  • 1
    But with a static property, you aren't just "de-initialising" it, you're removing it from the structure of the class. With a regular object, you're only affecting that instance, not the structure of the class it belongs to. You also wouldn't be able to *add* a new static property to a class at runtime: https://3v4l.org/ZgTRC. PHP doesn't support de-initialising the property other than setting it to null, unfortunately. – iainn Jan 04 '21 at 15:48
  • 1
    One option, I guess, would be to also add an `$initialised` property to the class, which would be either true/false. You could then check that instead of just the string, and you'd be able to keep the strong type-hinting. Personally, I don't think that's any cleaner than setting it to null, though. – iainn Jan 04 '21 at 15:51
  • @iainn I was thinking of unset as if I were asigning `undefined` in JavaScript. I agree with you, PHP does not seem to support this, but I hope there is some kind of workaround. The $initialised property is a possibility, but it would force me to add a lot of structural code and I prefer not to do so. Right now, the ?string seems to be the best option. But I really hate nulls XD – Joan Botella Jan 04 '21 at 16:40

0 Answers0