Skip to content

Callbacks

Greg Bowler edited this page May 4, 2026 · 1 revision

CallbackTypeSafeGetter is a separate interface for lookups that may need to compute or fetch a value on demand.

When the callback form is useful

This pattern is useful when a value might not already exist in the store.

Common examples include:

  • caches
  • lazy-loaded values
  • derived values that are expensive to compute

Instead of simply returning a stored value, the implementation can decide whether to call the callback.

The interface

CallbackTypeSafeGetter defines the same family of typed methods as TypeSafeGetter, but each one accepts a callback as well.

For example:

public function get(string $name, callable $callback):mixed;
public function getString(string $name, callable $callback):?string;
public function getDateTime(string $name, callable $callback):?DateTimeInterface;

Unlike NullableTypeSafeGetter, this repository does not provide a trait implementation for the callback interface. Each implementing class defines its own callback behaviour.

A small example

use DateTimeImmutable;
use DateTimeInterface;
use GT\TypeSafeGetter\CallbackTypeSafeGetter;
use TypeError;

class LazyStore implements CallbackTypeSafeGetter {
	private array $data = [];

	public function get(string $name, callable $callback):mixed {
		if(!array_key_exists($name, $this->data)) {
			$this->data[$name] = $callback();
		}

		return $this->data[$name];
	}

	public function getString(string $name, callable $callback):?string {
		return (string)$this->get($name, $callback);
	}

	public function getInt(string $name, callable $callback):?int {
		return (int)$this->get($name, $callback);
	}

	public function getFloat(string $name, callable $callback):?float {
		return (float)$this->get($name, $callback);
	}

	public function getBool(string $name, callable $callback):?bool {
		return (bool)$this->get($name, $callback);
	}

	public function getDateTime(string $name, callable $callback):?DateTimeInterface {
		return new DateTimeImmutable($this->get($name, $callback));
	}

	public function getInstance(string $name, string $className, callable $callback):object {
		$value = $this->get($name, $callback);
		if(!$value instanceof $className) {
			throw new TypeError("Value is not of type $className");
		}

		return $value;
	}
}

The important point is that the callback is part of the contract, but the rules for when it runs are up to the implementing class.

Relation to the rest of PHP.GT

Most PHP.GT packages that expose typed getters use TypeSafeGetter together with NullableTypeSafeGetter.

CallbackTypeSafeGetter appears in narrower cases where loading the value is part of the lookup operation itself, such as cache-style APIs.

Clone this wiki locally