spatie/once v3 has been released, now uses a PHP 8 WeakMap

Original – by Freek Van der Herten – 3 minute read

I've just released a new major version of the spatie/once package. This version uses the WeakMap class which is introduced in PHP 8. In this short post I'd like explain why this change was made.

Introducing the once package

The package offers a once function. The function can be used to easily cache results of expensive code. You can pass a closure to once. That closure will only be executed once, no matter how many times the function it resides it is called. Here's an example.

class MyClass {
    public function getRandomNumber(): int
        return once(function () {
            return rand();

$myObject = new MyClass();
$myObject->getRandomNumber(); // returns a random number
$myObject->getRandomNumber(); // will return the same number

No matter how many times you run $myObject->getRandomNumber() inside the same process you'll always get the same number.

Using some reflection magic once know the object and function it is called in. The cache used behind the scenes scopes all result according to the object it is called on.

Using our example class above, when we call getRandomNumber on a new instance, we get a new random number.

$myObject = new MyClass();
$myObject->getRandomNumber(); // returns a random number
$myObject->getRandomNumber(); // returns same number as line above

$myOtherObject = new MyClass();
$myOtherObject->getRandomNumber(); // returns a new random number
$myOtherObject->getRandomNumber(); // returns same number as line above

This behaviour is achieved using a WeakMap. Very shortly said, a WeakMap provides array like behaviour, but instead of using integers and strings as keys, it uses objects. When an object goes out of scope, the related entries in the WeakMap are automatically removed as well.

In this video I'll show you what a WeakMap is and how we use it inside the package.

In v2 of spatie/once we achieved WeakMap-like behaviour by performing some dark magic to detect when an object goes out of scope. I'm glad that we don't have to maintain this logic anymore.

By refactoring to using a WeakMap and PHP 8 types we got lose a quite a bit of code. You can see the changes in this PR. The packages now feels much more lighter.

Credits for the idea of the once function goes to Taylor Otwell. The code for this package is based upon the code he was kind enough to share with us a couple of years ago.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.



Gyro liked on 15th November 2020
Tauseef shah liked on 14th November 2020
Ali Mahdavi replied on 13th November 2020
Prefect videos 👌👌👌 Good job SPATIE 😎
Ali Mahdavi liked on 13th November 2020
Sumon Molla Selim, FRSA liked on 13th November 2020
Jeremy Lindblom retweeted on 13th November 2020
DeDaaf liked on 13th November 2020
Arthur Chocholate liked on 13th November 2020