Skip to main content
All ModelScribe drivers — built-in or custom — must implement HypathBel\ModelScribe\Contracts\DriverInterface. This two-method contract keeps the core package decoupled from any particular storage or transport layer, and makes custom drivers straightforward to write and test.

Methods

log(LogEntry $entry): void

Persist or dispatch a single audit log entry to the driver’s target destination.
LogEntry
required
An immutable LogEntry DTO (value object) carrying all audit data for this event. The DTO exposes the following readonly properties:The LogEntry also exposes a withLogName(string $logName): self method that returns a new instance with a different log name — used internally by the StackDriver to fan entries out to sub-drivers.
A LogEntry is constructed once by ModelScribe::log() or the observer and then handed to the driver. Because it is readonly, drivers must not attempt to modify it. If a driver needs a modified copy (e.g. a different logName), use $entry->withLogName('other').

prune(): int

Delete stale records from the driver’s backing store according to its configured retention policy. Returns the count of records removed as an int. Drivers that do not manage persistent state (for example, a webhook or queue driver that dispatches and forgets) should return 0.
prune() is called by ModelScribe::prune(?string $driver = null): int. The DriverInterface does not receive the driver name or any configuration at prune-time — each driver should read its own retention configuration (e.g. config('model-scribe.drivers.database.prune_after_days')) in its constructor or in the prune() implementation itself.

Built-in Drivers

Three driver classes ship with ModelScribe, all in the HypathBel\ModelScribe\Drivers namespace:

DriverManager

The DriverManager class resolves, caches, and creates driver instances. It is accessed via ModelScribe::getDriverManager().

driver(?string $name = null): DriverInterface

Resolves a driver by name, returning a cached instance on repeat calls. When $name is null, the global default from config('model-scribe.default') is used.

extend(string driver,Closuredriver, Closure callback): static

Register a factory closure for a custom driver name. The closure receives the driver’s configuration array and the DriverManager instance, and must return a DriverInterface implementation. Call this in a ServiceProvider::boot() method before any logging occurs.

flush(): void

Clears the internal cache of resolved driver instances. All subsequent calls to driver() will re-instantiate from configuration. Primarily useful in test suites where you need a clean driver state between test cases.

Writing a Custom Driver

Implement DriverInterface and register the class via extend(). The full pattern from contract to configuration looks like this: 1. Create the driver class
2. Register in a ServiceProvider
3. Configure in config/model-scribe.php
If your custom driver wraps a third-party service that may be unavailable (network timeouts, API rate limits), handle exceptions internally within log() and fail silently or push to a fallback — callers of ModelScribe::log() do not expect audit logging to throw.
Drivers are cached after the first resolution. If you call extend() after a driver of the same name has already been resolved, the cached instance will remain in use until flush() is called.