Giter Club home page Giter Club logo

once's Introduction

A magic memoization function

Latest Version on Packagist Software License Build Status Quality Score StyleCI Total Downloads

This package contains a once function. You can pass a callable to it. Here's quick example:

class MyClass
{
    function getNumber()
    {
        return once(function () {
            return rand(1, 10000);
        });
    }
}

No matter how many times you run (new MyClass())->getNumber() inside the same request you'll always get the same number.

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Installation

You can install the package via composer:

composer require spatie/once

Usage

The once function accepts a callable.

class MyClass
{
    function getNumber()
    {
        return once(function () {
            return rand(1, 10000);
        });
    }
}

No matter how many times you run (new MyClass())->getNumber() you'll always get the same number.

The once function will only run once per combination of argument values the containing method receives.

class MyClass
{
    public function getNumberForLetter($letter)
    {
        return once(function () use ($letter) {
            return $letter . rand(1, 10000000);
        });
    }
}

So calling (new MyClass())->getNumberForLetter('A') will always return the same result, but calling (new MyClass())->getNumberForLetter('B') will return something else.

Note: In order to use once on classes that have the magic method __get defined, you will need to either manually define the __memoized property on your object, or use the include MemoizeAwareTrait. This applies particularly to Laravel Eloquent models.

Behind the curtains

Let's go over the code of the once function to learn how all the magic works.

In short: it will execute the given callable and save the result in a an array in the __memoized property of the instance once was called in. When we detect that once has already run before, we're just going to return the value stored inside the __memoized array instead of executing the callable again.

The first thing it does it calling debug_backtrace. We'll use the output to determine in which function and class once is called and to get access to the object that function is running in. Yeah, we're already in voodoo-land. The output of the debug_backtrace is passed to a new instance of Backtrace. That class is just a simple wrapper so we can work more easily with the backtrace.

$trace = debug_backtrace(
    DEBUG_BACKTRACE_PROVIDE_OBJECT, 2
)[1];

$backtrace = new Backtrace($trace);

Next, we're going to check if once was called from within an object. If it was called from a static method or outside a class, we just bail out.

if (! $object = $backtrace->getObject()) {
   throw new Exception('Cannot use `once` outside a class');
}

Now that we're certain once is called within an instance of a class we're going to calculate a hash of the backtrace. This hash will be unique per function once was called in and the values of the arguments that function receives.

$hash = $backtrace->getArgumentHash();

Finally we will check if there's already a value stored for the given hash. If not, then execute the given $callback and store the result in the __memoized array on the object. In the other case just return the value in the __memoized array (the $callback isn't executed).

if (! isset($object->__memoized[$hash])) {
   $result = call_user_func($callback, $backtrace->getArguments());
   $object->__memoized[$hash] = $result;
}

Caveats

  • you can only use the once function in non-static class methods
  • if you need to serialize an object that uses once be sure to unset the __memoized property. A perfect place for that would be the __sleep magic method

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

composer test

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Postcardware

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.

We publish all received postcards on our company website.

Credits

Credit 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.

Support us

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Does your business depend on our contributions? Reach out and support us on Patreon. All pledges will be dedicated to allocating workforce on maintenance and new awesome stuff.

License

The MIT License (MIT). Please see License File for more information.

once's People

Contributors

akoepcke avatar carusogabriel avatar freekmurze avatar jimbojsb avatar nightlinus avatar sebastiandedeyne avatar taylorotwell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.