VOOZH about

URL: https://deepwiki.com/hypervel/prompts/10.2-fallback-implementations

⇱ Fallback Implementations | hypervel/prompts | DeepWiki


Loading...
Last indexed: 7 February 2026 (2e2181)
Menu

Fallback Implementations

Purpose and Scope

This document explains the Fallback trait and how it enables custom implementations for prompt classes when normal interactive terminal I/O is not possible or desirable. The fallback system provides a global registry mechanism where alternative implementations can be registered for any prompt class, allowing developers to programmatically control prompt behavior in testing, automation, or specialized runtime environments.

For information about mocking terminal I/O in tests, see page 10.1 (Testing with Mocked Terminal I/O). For information about the built-in non-interactive mode that uses default values via the Interactivity trait, see section 4.3 (Terminal Integration).


What is a Fallback?

A fallback is an alternative execution path for a prompt class that bypasses normal terminal interaction. When fallbacks are enabled, prompts check for registered fallback closures before attempting to render and collect input. If a fallback closure exists for the prompt's class, it is executed instead of the normal prompt() flow.

Fallbacks are implemented via the Fallback trait src/Concerns/Fallback.php10 which is mixed into the base Prompt class src/Prompt.php22 This provides all prompt types with fallback capabilities through inheritance.

Key differences from other approaches:

ApproachMechanismUse Case
FallbackGlobal registry of closuresCustom logic per prompt class in specialized environments
Non-interactive mode (Interactivity trait)Default value when !$this->interactiveAutomated scripts, CI/CD with predetermined inputs
FakesInputOutput (Testing)Simulated input queue and output bufferPHPUnit tests that need to verify specific interactions

Architecture of the Fallback System

The Fallback trait implements a static registry pattern that maintains a global mapping of prompt classes to fallback closures.

Fallback Trait Structure


Sources: src/Concerns/Fallback.php10-63


Static Properties and State Management

The trait maintains two static properties that persist across all instances:

$shouldFallback Flag


The $shouldFallback flag is a static boolean src/Concerns/Fallback.php15 that determines whether the fallback system is active. It is set via fallbackWhen() src/Concerns/Fallback.php27-30 using an OR operation, meaning once enabled, it cannot be disabled for the lifetime of the PHP process.

$fallbacks Registry

The $fallbacks array src/Concerns/Fallback.php22 is a static associative array with this structure:

KeyValueDescription
class-stringClosure($this): mixedFully qualified class name maps to a closure that receives the prompt instance

Example registration:


Sources: src/Concerns/Fallback.php15-22


Fallback Execution Flow

Registration and Invocation Sequence


Sources: src/Concerns/Fallback.php27-62


Method Reference

fallbackWhen(bool $condition): void

Enables the fallback system when the condition is true src/Concerns/Fallback.php27-30 Uses an OR operation with the existing flag, so once enabled, subsequent calls with false will not disable it.


shouldFallback(): bool

Returns true if both conditions are met src/Concerns/Fallback.php35-38:

  1. The global $shouldFallback flag is true
  2. A fallback closure is registered for the calling class (isset(static::$fallbacks[static::class]))

fallbackUsing(Closure $fallback): void

Registers a fallback closure for the calling class src/Concerns/Fallback.php45-48 The closure receives the prompt instance as its parameter and should return the appropriate type for that prompt.


fallback(): mixed

Executes the registered fallback closure for the current instance src/Concerns/Fallback.php53-62 Throws a RuntimeException if no fallback is registered for the class.

Sources: src/Concerns/Fallback.php27-62


Fallback Decision Tree


The decision to use a fallback happens in the prompt class's prompt() method (implementation varies by prompt type). The typical pattern checks shouldFallback() early in the prompt flow.

Sources: src/Concerns/Fallback.php35-38


Use Cases and Examples

Use Case 1: Automated Testing Environment

Register fallbacks to provide deterministic responses for all prompts during integration tests:


Use Case 2: Custom Implementation for Specialized Environment

Replace prompt behavior with custom logic, such as reading from a configuration file:


Use Case 3: Dynamic Fallback Based on Prompt Properties

The fallback closure receives the prompt instance src/Concerns/Fallback.php61 allowing access to all public properties:


Use Case 4: Handling Terminal Setup Failures

When running in environments where terminal control is unavailable (e.g., Docker containers, CI systems), register fallbacks as a safety net. The automatic fallback mechanism src/Prompt.php121-128 will activate them if Terminal::setTty() fails:


Sources: src/Concerns/Fallback.php53-62 src/Prompt.php121-128


Error Handling

Missing Fallback Registration

Calling fallback() when no closure is registered for the class throws a RuntimeException src/Concerns/Fallback.php57-59:


Error message format:

No fallback implementation registered for [Hypervel\Prompts\TextPrompt]

Type Safety Considerations

The fallback closure should return a value compatible with the prompt's expected return type:

Prompt ClassExpected Return Type
TextPromptstring
SelectPromptstring|int
MultiSelectPromptarray<int|string>
ConfirmPromptbool

The trait does not enforce type checking, so developers must ensure fallback closures return appropriate types.

Sources: src/Concerns/Fallback.php53-62


Comparison Matrix

Fallback vs. Other Non-Interactive Approaches


When to use each approach:

  • Fallback: Custom application logic needed in production environments (e.g., reading from config files, environment variables, or external APIs)
  • Interactivity/Default values: Simple automation where predetermined values are sufficient (CI/CD scripts)
  • FakesInputOutput: PHPUnit tests that need to verify specific prompt interactions and output

Sources: src/Concerns/Fallback.php10-63


Class-Specific Fallback Registration

Each prompt class maintains its own fallback registration independently:


The static $fallbacks array uses static::class as the key src/Concerns/Fallback.php47 ensuring each prompt class can have its own fallback implementation while sharing the global enable flag.

Sources: src/Concerns/Fallback.php45-48


Integration with Prompt Lifecycle

Early Fallback Check in Prompt::prompt()

The Prompt base class checks for fallbacks early in the prompt() method execution src/Prompt.php104-161 The check occurs before terminal initialization:


Sources: src/Prompt.php104-161 src/Concerns/Fallback.php35-38 src/Concerns/Fallback.php53-62


Automatic Fallback on Terminal Failure

The Prompt::prompt() method includes an automatic fallback mechanism when terminal setup fails src/Prompt.php121-128:


This pattern provides resilience when terminal operations fail (e.g., in environments without TTY support), automatically switching to the fallback implementation if one is registered.

Sources: src/Prompt.php121-128


Progress Class Exception

The Progress class inherits the Fallback trait but overrides the prompt() method to throw a RuntimeException src/Progress.php184-187:


This is because Progress uses a different execution model (start(), advance(), finish() methods) and is not designed for the standard prompt workflow. Fallbacks cannot be used with Progress instances.

Sources: src/Progress.php184-187


Limitations and Considerations

Static State Management

The fallback system uses static properties src/Concerns/Fallback.php15 src/Concerns/Fallback.php22 which means:

  1. Global scope: All instances of all prompt classes share the same enable flag
  2. Process lifetime: Once fallbackWhen(true) is called, it cannot be undone
  3. Testing isolation: Tests that enable fallbacks may affect subsequent tests unless the PHP process is reset

OR Operation Behavior

The fallbackWhen() method uses an OR operation src/Concerns/Fallback.php29:


This means calling fallbackWhen(false) after fallbackWhen(true) will not disable fallbacks. This is intentional to prevent accidental disabling in complex applications.

Closure Binding

Fallback closures receive the prompt instance as a parameter src/Concerns/Fallback.php61 not via $this binding. This means closures cannot access private/protected properties of the prompt class unless explicitly made accessible.

Sources: src/Concerns/Fallback.php15 src/Concerns/Fallback.php22 src/Concerns/Fallback.php29 src/Concerns/Fallback.php61

Refresh this wiki

On this page