Simple PHP trait to memoize function calls.

v1.0.3 2023-02-15 21:48 UTC

This package is auto-updated.

Last update: 2024-12-08 06:42:52 UTC


README

Latest Version on Packagist Tests Check & fix styling License

Introduction

This package provides you with a simple PHP trait, which adds high-performance memoization to your classes!

Installation

$ composer require laracraft-tech/memoize

Usage

The memoize method accepts a callable.

use LaracraftTech\Memoize\HasMemoization;

$myClass = new class()
{    
    use HasMemoization;

    public function getNumber(): int
    {
        return $this->memoize(function () {
            return rand(1, 10000);
        });
    }
};

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

The memoize method will only run once per combination of use variables the closure receives.

$myClass = new class()
{
    use HasMemoization;
    
    public function getNumberForLetter($letter)
    {
        return $this->memoize(function () use ($letter) {
            return $letter . rand(1, 10000000);
        });
    }
}

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

Some memoization packages uses the arguments of the containing method for the once per combination idea. We think this feels a bit unintuitive and in certain circumstances will affect performance. So we use the use variables of the closure as the once per combination key. As a fallback, if you like/need to, we also let you fully self define your once per combination key in a second optional parameter of the closure.

use LaracraftTech\Memoize\HasMemoization;

$myClass = new class()
{
    use HasMemoization;
    
    public function processSomethingHeavy1($someModel)
    {
        // ...
        
        $relation = $this->memoize(function () use ($someModel) {
            return Foo::find($someModel->foo_relation_id);
        }, $someModel->foo_relation_id); // <--- custom once per combination key
        
        // ...
    }
    
    // you could also do something like this (maybe more convinient)
    public function processSomethingHeavy2($someModel)
    {
        // ...
        
        $foo_relation_id = $someModel->foo_relation_id;
        $relation = $this->memoize(function () use ($foo_relation_id) {
            return Foo::find($foo_relation_id);
        });
        
        // ...
    }
    
    // this would work but will lose performance on each new $someModel even foo_relation_id would be the same
    public function processSomethingHeavy3($someModel)
    {
        // ...
        
        $relation = $this->memoize(function () use ($someModel) {
            return Foo::find($someModel->foo_relation_id);
        });
        
        // ...
    }
}

So when calling $myClass->processSomethingHeavy1(SomeModel::find(1)) the variable $relation will always have the same value like in $myClass->processSomethingHeavy1(SomeModel::find(2)) as long as they have the same foo_relation_id. In some other memoization packges you would lose performance here, cause the containing method parameter ($someModel) has changed... Note that processSomethingHeavy3 would also lose performance, even though the foo_relation_id would be the same, cause here also the changed $someModel would be used as the combination key and that model would have at least a different id.

Enable/Disable

You can globally enable or disable the memoize cache by setting MEMOIZATION_GLOBALLY_DISABLED to true in your .env file.

If you only want to disable to memoize cache for a specifiy class, do something like this:

use LaracraftTech\Memoize\HasMemoization;

class MyClass
{
    use HasMemoization;
    
    public function __construct()
    {
        $this->disableMemoization();
    }
}

Change log

Please see the changelog for more information on what has changed recently.

Testing

$ composer test

Contributing

Please see contributing.md for details and a todolist.

Security

If you discover any security related issues, please email zacharias.creutznacher@gmail.com instead of using the issue tracker.

Credits

License

MIT. Please see the license file for more information.