Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 133 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@

A flexible memoization library for memory caching.

## Table of Contents

- [Memoization](#memoization)
- [Installation](#installation)
- [Notes on examples](#notes-on-examples)
- [Usage](#usage)
- [Simple example](#simple-example)
- [Setting a nested structure](#setting-a-nested-structure)
- [Purging a nested structure](#purging-a-nested-structure)
- [Caching with closures](#caching-with-closures)
- [Using with a dependency injection container](#using-with-a-dependency-injection-container)
- [Drivers](#drivers)
- [MemoryDriver](#memorydriver)

## Memoization

[Memoization](https://en.wikipedia.org/wiki/Memoization) is the process of caching the results of expensive function calls so that they can be reused when the same inputs occur again.
Expand All @@ -29,26 +43,30 @@ All namespaces within the examples will be using the `StellarWP\Memoize`, howeve
### Simple example

```php
use StellarWP\Memoize\Memoize;
use StellarWP\Memoize\Memoizer;

$memoizer = new Memoizer();

Memoize::set('foo', 'bar');
$memoizer->set('foo', 'bar');

if (Memoize::has('foo')) {
echo Memoize::get('foo'); // Outputs: bar
if ($memoizer->has('foo')) {
echo $memoizer->get('foo'); // Outputs: bar
}

// Unsets foo from the memoization cache.
Memoize::forget('foo');
$memoizer->forget('foo');
```

### Setting a nested structure

Memoize allows you to use dot notation to set, get, and forget values from a nested structure. This allows you to easily add/fetch values and then purge individual items or whole collections of items.

```php
use StellarWP\Memoize\Memoize;
use StellarWP\Memoize\Memoizer;

$memoizer = new Memoizer();

Memoize::set('foo.bar.bork', 'baz');
$memoizer->set('foo.bar.bork', 'baz');

// This results in the following cache:
// [
Expand All @@ -60,27 +78,29 @@ Memoize::set('foo.bar.bork', 'baz');
// ]

// You can fetch the value like so:
$value = Memoize::get('foo.bar.bork');
$value = $memoizer->get('foo.bar.bork');
echo $value; // Outputs: baz

// You can fetch anywhere up the chain:
$value = Memoize::get('foo.bar');
$value = $memoizer->get('foo.bar');
echo $value; // Outputs: [ 'bork' => 'baz' ]

$value = Memoize::get('foo');
$value = $memoizer->get('foo');
echo $value; // Outputs: [ 'bar' => [ 'bork' => 'baz' ] ]

$value = Memoize::get();
$value = $memoizer->get();
echo $value; // Outputs: [ 'foo' => [ 'bar' => [ 'bork' => 'baz' ] ] ]
```

#### Purging a nested structure

```php
use StellarWP\Memoize\Memoize;
use StellarWP\Memoize\Memoizer;

Memoize::set('foo.bar.bork', 'baz');
Memoize::forget('foo.bar.bork');
$memoizer = new Memoizer();

$memoizer->set('foo.bar.bork', 'baz');
$memoizer->forget('foo.bar.bork');

// This results in the following cache:
// [
Expand All @@ -89,67 +109,141 @@ Memoize::forget('foo.bar.bork');
// ],
// ]

Memoize::forget('foo.bar');
$memoizer->forget('foo.bar');

// This results in the following cache:
// [
// 'foo' => [],
// ]

Memoize::forget('foo');
$memoizer->forget('foo');

// This results in the following cache:
// []

Memoize::forget();
$memoizer->forget();

// This results in the following cache:
// []
```

### Caching an expensive execution
### Caching with closures

Memoize also supports using closures as values that get resolved before setting in the cache.

```php
use StellarWP\Memoize\Memoize;
use StellarWP\Memoize\Memoizer;

function my_expensive_function() {
$key = __FUNCTION__;
$value = Memoize::get($key);
$memoizer = new Memoizer();

if ( ! $value ) {
// Do some crazy expensive stuff to set:
$memoizer->set('foo', static function () {
return 'bar';
});

$value = $thing;
echo $memoizer->get('foo'); // Outputs: bar
```

### Using with a dependency injection container

#### Project class

```php
<?php

Memoize::set($key, $value);
declare(strict_types=1);

namespace StellarWP\MyProject;

use StellarWP\Memoize\MemoizerInterface;

// Dependencies automatically auto-wired due to the definitions in ServiceProvider.php via
// $this->container->get( MyProjectClass::class )

/**
* An example class inside your project using the Memoize library.
*/
class MyProjectClass
{

private MemoizerInterface $memoizer;

public function __construct( MemoizerInterface $memoizer )
{
$this->memoizer = $memoizer;
}

return $value;
public function get( string $name ): string
{
$result = $this->memoizer->get( $name );

if ( ! $result ) {
$result = 'some very expensive operation';

$this->memoizer->set( $name, $result );
}

return $result;
}

public function delete( string $name ): bool
{
$this->memoizer->forget( $name );

// Run delete operation...

return true;
}
}
```

## Drivers
#### Service Provider

Memoize comes with a few drivers out of the box, but you can also create your own.
```php
<?php

### MemoryDriver
declare(strict_types=1);

The `MemoryDriver` is a simple in-memory driver. Basically, there's a static variable in the driver that holds the memoized values. You can manually specify the use of this driver like so:
namespace StellarWP\Memoize;

```php
use StellarWP\Memoize\Config;
use StellarWP\ContainerContract\ContainerInterface;
use StellarWP\Memoize\Contracts\DriverInterface;
use StellarWP\Memoize\Contracts\MemoizerInterface;
use StellarWP\Memoize\Drivers\MemoryDriver;

Config::setDriver(new MemoryDriver());
/**
* Container ServiceProvider to tell the DI Container how to build everything when another
* instance is requested from the Container that uses our interface.
*
* @example $this->container->get( MyProjectClass::class );
*/
final class ServiceProvider
{
private ContainerInterface $container;

public function __construct(ContainerInterface $container)
{
$this->container = $container;
}

public function register(): void
{
$this->container->singleton( DriverInterface::class, MemoryDriver::class );
$this->container->bind( MemoizerInterface::class, Memoizer::class );
}
}
```

### WpCacheDriver
## Drivers

The `WpCacheDriver` is the default driver and uses WordPress's `wp_cache_set` and `wp_cache_get` functions and stores all of the memoized values in a single cache entry. Getting and setting memoized values is done by fetching from cache, manipulating (if needed), and saving back to cache (if needed).
Memoize comes with a single driver out of the box, but you can also create your own using the `StellarWP\Memoize\Contracts\DriverInterface`.

### MemoryDriver

The `MemoryDriver` is a simple in-memory driver. Basically, contains an array property in the driver that holds the memoized values. You can manually specify the use of this driver or any other driver like so:

```php
use StellarWP\Memoize\Config;
use StellarWP\Memoize\Drivers\WpCacheDriver;
use StellarWP\Memoize\Memoizer;
use StellarWP\Memoize\Drivers\MemoryDriver;

Config::setDriver(new WpCacheDriver());
$memoizer = new Memoizer(new MemoryDriver());
```
61 changes: 0 additions & 61 deletions src/Memoize/Config.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace StellarWP\Memoize\Drivers\Contracts;
namespace StellarWP\Memoize\Contracts;

interface DriverInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

declare(strict_types=1);

namespace StellarWP\Memoize;
namespace StellarWP\Memoize\Contracts;

final class Memoize
interface MemoizerInterface
{
/**
* Get a value from the memoization cache.
*
* @param ?string $key The cache key using dot notation. If null, the entire cache will be returned.
* @return mixed
*/
public static function get(?string $key = null)
{
return Config::getDriver()->get($key);
}
public function get(?string $key = null);

/**
* Set a value in the memoization cache.
Expand All @@ -24,30 +21,21 @@ public static function get(?string $key = null)
* @param mixed $value The value to store in the cache.
* @return void
*/
public static function set(string $key, $value): void
{
Config::getDriver()->set($key, $value);
}
public function set(string $key, $value): void;

/**
* Check if a key exists in the memoization cache.
*
* @param string $key The cache key using dot notation.
* @return boolean
* @return bool
*/
public static function has(string $key): bool
{
return Config::getDriver()->has($key);
}
public function has(string $key): bool;

/**
* Remove a key from the memoization cache.
*
* @param ?string $key The cache key using dot notation. If null, the entire cache will be cleared.
* @return void
*/
public static function forget(?string $key = null): void
{
Config::getDriver()->forget($key);
}
public function forget(?string $key = null): void;
}
Loading
Loading