Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Emdrive Laravel Package

maksslesarenko/emdrive

EMDrive is a Laravel/PHP package by maksslesarenko that provides a lightweight, framework-friendly way to integrate EMDrive functionality into your application. See the repository for installation, configuration, and usage details.

View on GitHub
Deep Wiki
Context7

Getting Started

emdrive is a driver-based abstraction package: it exposes a manager that resolves one implementation from a set defined in config, and you interact with it through a facade or container binding. The install is trivial; the meaningful work is discovering which contract you're meant to call and which driver is active.

  1. Install and read composer.json before anything else.

    composer require maksslesarenko/emdrive
    

    Open vendor/maksslesarenko/emdrive/composer.json and check three things: the require block (PHP and illuminate/* constraints), the extra.laravel block (auto-discovery of provider and facade alias), and whether a config/ directory ships with the package. If extra.laravel is missing, you must register the provider and facade manually in config/app.php (Laravel 10) or bootstrap/providers.php (Laravel 11+).

  2. Publish the config and read every key.

    php artisan vendor:publish --provider="Maksslesarenko\Emdrive\EmdriveServiceProvider" --tag=config
    

    The published config/emdrive.php is the source of truth for driver names, default driver, and per-driver options. Skim it before you read any src/ file — it tells you what the package expects you to configure.

  3. Skim src/ in this order: the service provider (what gets bound and how), the manager class (how drivers are resolved and cached), the Contracts/ directory (the interfaces you should type-hint), then each Drivers/ directory (the implementations).

  4. First use case — resolve the default driver and call it once:

    $emdrive = app(\Maksslesarenko\Emdrive\Contracts\EmdriveInterface::class);
    $result = $emdrive->handle($payload);
    

    If the interface doesn't exist, use the facade instead (Emdrive::handle($payload)). Get one successful call and one deliberate failure (wrong driver name in config) before wiring it into a feature — the failure path is where you learn how the manager reports misconfiguration.

  5. Confirm nothing else breaks. Run php artisan config:clear after publishing, then composer dump-autoload. If the facade alias collides with an existing one in your app, alias it explicitly to avoid silent resolution to the wrong class.

Implementation Patterns

Default driver in config, per-environment overrides. The natural pattern is: config/emdrive.php declares 'default' => env('EMDRIVE_DRIVER', 'sync') and a drivers map. Set EMDRIVE_DRIVER=queue in staging/production and leave sync locally. This is the whole point of the package — resist the temptation to hardcode a driver name at the call site.

Inject the interface, not the facade, in domain code. The facade is fine for controllers and Artisan commands, but service classes and anything you'll unit-test should type-hint the contract:

public function __construct(
    private readonly \Maksslesarenko\Emdrive\Contracts\EmdriveInterface $emdrive,
) {}

This makes the package swappable later, which matters given there are zero dependents and no maintenance commitment.

Swap drivers in tests, don't mock HTTP. Register a fake driver in a service provider in tests/TestCase.php, or rebind the interface to an anonymous implementation:

$this->app->bind(EmdriveInterface::class, fn () => new class implements EmdriveInterface {
    public function handle($payload): mixed { return ['ok' => true]; }
});

Prefer this over Facade::shouldReceive(...) — the fake path exercises the manager's resolution logic, the facade mock doesn't.

Drive variation through config, not branches. Two use cases: (a) a "null" or "log" driver for local development, and (b) different drivers per tenant/environment. For (a), add a 'null' driver in your own service provider if the package doesn't ship one. For (b), override emdrive.default in a tenant-aware service provider — do not add if ($tenant->plan === 'pro') checks around every call.

Wrap for the long term. Because the package is effectively a reference implementation, put a thin anti-corruption layer in front of it:

namespace App\Support\Emdrive;

interface EmdriveClient { public function run(array $payload): array; }

Implement it against the package once. Every call site depends on EmdriveClient. If the package is abandoned, you rewrite one adapter class instead of grepping the codebase.

Register custom drivers in your own provider. Most driver managers follow the extend()/driver() pattern. In AppServiceProvider::boot(), call the manager's extend('custom', fn ($app) => new CustomDriver(...)). This is the extension point to check for in src/ before you assume you need to fork — if it's missing, that's a fork signal.

Config-cache discipline. Always follow publish/edit with php artisan config:cache in deploy and php artisan config:clear locally. Driver options are read from config('emdrive.*'), so a stale cache silently runs the wrong driver in production — a nasty class of bug to debug.

Gotchas and Tips

  • Zero dependents means zero bug reports. You are the first person to run this in production. Pin an exact version in composer.json ("maksslesarenko/emdrive": "1.0.0" not "^1.0") until you've read the source and confirmed the maintenance posture. A minor bump without a changelog is otherwise invisible.

  • Verify the driver manager's caching behavior. Most managers cache the resolved driver per name. If you resolve a driver, change config at runtime, then resolve again expecting a different class, you'll get the old one. Call the manager's forgetDrivers() (or equivalent) between test cases that swap drivers.

  • Check that extra.laravel actually auto-discovers both the provider and the facade. Auto-discovery of a provider without the facade alias means Emdrive:: will throw Class not found while app(EmdriveInterface::class) works. This trips people up when porting example code from the README into a real project.

  • Debug driver resolution with a one-liner. When you can't tell which driver is active, add dump(get_class(app(EmdriveInterface::class))); in a route or tinker session. If the manager returns the wrong one, check the default key in config/emdrive.php after config:cache — the env var name might not match what the config file expects.

  • Publish only the config, not migrations, unless you've reviewed the schema. The package description doesn't mention persistence. If vendor:publish offers a migrations tag, read every migration before running it — schema coupling is the one failure mode you can't cleanly unwind, and if it exists, reject the package rather than adopt it.

  • Facade aliasing conflicts. Emdrive is a short alias that could collide with a model or a future first-party package. If your app already has one, register the package under a prefix ('aliases' => ['Emdrive' => ...] in your own config) or skip the facade entirely and use app().

  • Exception behavior on bad config is undocumented. Test it explicitly: set EMDRIVE_DRIVER=nonsense and call the facade. Does it throw InvalidArgumentException, return null, or log-and-fallback? You need to know this before production, not during an incident. Add your own guard (a config validation in a ValidateEmdriveConfig boot hook) if the failure mode is silent.

  • Extension points to look for (in order of preference): (1) an extend() method on the manager, (2) a contract you can bind in your own provider, (3) a withDriver() / driver('name') method on the facade root for per-call overrides. If none exist, you're forking — budget for that explicitly and vendor the source into packages/emdrive/ rather than depending on the upstream tag.

  • Don't reach for this on the critical path. Driver-based abstraction hides which implementation runs, which is exactly the wrong property for payments, auth, or anything where "which code executed" needs to be obvious from a stack trace. Use it for internal tooling, batch jobs, and developer-facing features where the blast radius of a silent driver swap is small.

  • Read the package's own tests before reading its source. If tests/ exists, the test file for each driver is the most honest documentation of what the contract requires and where the edge cases are. If tests/ is empty or absent, treat every method's behavior as unverified on your PHP/Laravel version and write your own contract test against it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource