Skip to main content

Fallback chains

A request can list several engines. They are tried in order until one returns content.

How the chain runs

generate() builds the list as the primary engine followed by every fallback engine, in registration order. For each engine:

  • If it returns a non-null string, that result is wrapped in a GeneratedAvatar and returned immediately.
  • If it returns null, the engine has declined (for example, the initials engine has no usable initials, or DiceBear was given an invalid style). The builder records the reason and moves to the next engine.
  • If it throws, the exception is recorded and the builder moves to the next engine — unless debug mode is enabled.

If the list is exhausted without a result, generate() throws AllEnginesFailedException.

Building a chain

use Renfordt\AvatarSmithy\Avatar;

$avatar = Avatar::engine('gravatar') // primary
->fallbackTo('dicebear') // tried if gravatar declines/fails
->fallbackTo('initials') // final, local fallback
->seed('user@example.com')
->name('User Name')
->generate();

try() behaves the same as engine() for the first engine and as fallbackTo() afterwards, which is convenient with Avatar::for():

$avatar = Avatar::for($user)
->try('gravatar')
->fallbackTo('initials')
->generate();

Choosing a final engine

Remote engines (Gravatar, DiceBear) depend on a network request and can decline or fail. End the chain with a local engine that almost always succeeds. The initials engine succeeds whenever the name yields at least one usable initial; if the name is empty it declines, so a generative local engine such as pixel, gradient, or bauhaus is a safe terminal choice when names may be missing.

Inspecting failures

After a partial or total failure you can read what happened:

$builder = Avatar::engine('gravatar')->fallbackTo('initials')->seed($email);

$avatar = $builder->generate();

foreach ($builder->getLastErrors() as $failure) {
// ['engine' => FQCN, 'error' => string, 'exception' => ?Throwable]
}

getLastErrors() is reset at the start of each generate() call.

Debug mode

With debugMode(true), the first failing engine stops the chain and its exception is rethrown as EngineFailedException (wrapping the original). Use it while developing to surface the underlying error instead of silently falling through.

Avatar::engine('dicebear')
->debugMode()
->seed($email)
->generate(); // throws EngineFailedException on the first failure