ueberdosis/pandoc
ueberdosis/pandoc provides a fluent PHP and Laravel wrapper around Pandoc, letting you convert documents between Markdown, HTML, DOCX, PDF, and many other formats with a clean API, configurable options, and simple integration into your applications.
Install the package (typically as a dev dependency) and publish its config:
composer require --dev vendor/package
php artisan vendor:publish --tag=package-config
Read three things first, in this order:
config/<package>.php — most of the day-to-day knobs live here, including the default for standalone execution.php artisan <command> --help) — the --standalone flag and its siblings are the fastest way to see what the builder methods map to.A good first use case is simply running the command in an existing Laravel app and comparing the two modes:
php artisan package:command # boots the framework, resolves the container
php artisan package:command --standalone # runs without booting the app
What's new in 0.9.0: a noStandalone() method on the fluent configuration object. It opts your invocation out of standalone execution, regardless of the ambient default. This is the method to reach for when the work you're doing genuinely needs the container (Eloquent, config(), bindings, facades) and you don't want a stray --standalone in CI or a wrapper script to silently strip the framework out from under you.
Package::configure()
->noStandalone()
->run();
If you have no reason to touch standalone mode at all, 0.9.0 is additive and non-breaking — you can upgrade without changing code, though pinning to ^0.9 is sensible.
Force framework context where it matters. Any code path that touches the database, config repository, or container bindings should be explicit about it. Chaining noStandalone() at the call site is clearer than relying on a config default that someone may flip later:
// app/Console/Commands/ExportReports.php
public function handle(): int
{
return Package::configure()
->noStandalone()
->output($this->output)
->run();
}
Keep the default for scripts and CI. The whole point of standalone mode is speed — no app boot, no service providers, no DB connection. Let the default stand for lint-style, file-scanning, or code-generation work where the framework is irrelevant. Only opt out per invocation, not globally, unless your entire app depends on container access.
Wrap it in an Artisan command rather than shelling out. You get the output helper, exit codes, and testability for free. Delegate flags rather than hardcoding them, and only add noStandalone() where it is a genuine requirement — not as a blanket safety net.
Test both paths. noStandalone() is easy to cover with an Artisan assertion, and doing so documents intent:
it('runs in framework mode', function () {
Package::configure()->noStandalone()->run();
// or, at the command level:
$this->artisan('package:command')->assertSuccessful();
});
Layer it with config. The builder method wins over the config default, which wins over the CLI flag — verify that precedence in the package's resolution code before you build anything clever on top of it.
noStandalone() is not a CLI lock. It disables standalone mode for builder-driven invocations. If a user runs the underlying command directly with --standalone, they will still get standalone behaviour unless the command itself rejects the flag. Don't treat it as a security boundary.config(), env(), Eloquent, and facades are unavailable or unreliable. If you see Target class [...] does not exist or a null config value, the first thing to check is whether the code accidentally ran standalone.noStandalone() after a terminal method like run() is a silent no-op. Chain it before the execution call.php artisan config:cache will break it. Prefer scalar config values and put conditional logic in a service provider or at the call site.-v). Nine times out of ten the surprise is an inherited default from a published config file that predates your upgrade.noStandalone() there, keeping call sites clean.How can I help you explore Laravel packages today?