DI and actions
The facade is the recommended default, not the only way in. Three entry points reach the same behaviour:
- The Certificates facade — the shortest form, used throughout these docs.
- The manager, RoundlyConsulting\Certificates\CertificatesManager — the facade root. Inject it through the constructor for the same API as an explicit dependency, with no static calls.
- The actions — single-purpose classes with one execute(), for composing into your own actions, jobs and commands.
Inject the manager, or call an action
use RoundlyConsulting\Certificates\Actions\RevokeCertificateAction;
use RoundlyConsulting\Certificates\CertificatesManager;
use RoundlyConsulting\Certificates\DataTransferObjects\IssueCertificateData;
final class SiteCertificates
{
public function __construct(private CertificatesManager $certificates) {}
public function launch(string $domain): void
{
$this->certificates->issue(IssueCertificateData::make($domain));
$this->certificates->for($domain)->renewLater();
}
}
// The raw use case, e.g. from your own action:
app(RevokeCertificateAction::class)->execute($certificate, 'key compromise');The certificates() helper returns the same manager instance as app(CertificatesManager::class). It used to return the driver manager — that is now CertificateProviderManager, reached through Certificates::driver() and Certificates::extend():
use RoundlyConsulting\Certificates\CertificatesManager;
$certificates = app(CertificatesManager::class); // the facade root
$certificates = certificates(); // the helper — the same instance
certificates()->renew('shop.example.com');Facade method → action
Every action lives in RoundlyConsulting\Certificates\Actions as a final readonly class with constructor injection. All of them are reachable from the facade; none is internal:
| Facade method | Action | execute() |
|---|---|---|
issue(), issueIfMissing(), generate(), for()->issue() | IssueCertificateAction | (IssueCertificateData $data, ?string $connection = null): Certificate |
renew(), for()->renew() | RenewCertificateAction | (Certificate $certificate): Certificate |
renewDue() | RenewDueCertificatesAction | (?int $thresholdDays = null, bool $queue = false, ?string $connection = null): RenewalReport |
revoke(), for()->revoke() | RevokeCertificateAction | (Certificate $certificate, ?string $reason = null): Certificate |
expire(), for()->expire() | ExpireCertificateAction | (Certificate $certificate): Certificate |
sync() | SyncCertificatesAction | (?string $driver = null, ?string $connection = null): int |
prune() | PruneCertificatesAction | (int $days = 30, CertificateStatus|string|null $status = null, ?string $connection = null): int |
renewLater(), for()->renewLater() | — (dispatches RenewCertificateJob) | The job runs RenewCertificateAction. |
The manager resolves the action from the container on every call, so a container binding that overrides an action applies to the facade, the handle and the commands alike. IssueCertificateAction, RenewDueCertificatesAction, SyncCertificatesAction and PruneCertificatesAction take the registry connection as their last argument; the others act on the Certificate you pass. IssueCertificateAction takes an IssueCertificateData DTO:
use RoundlyConsulting\Certificates\Actions\IssueCertificateAction;
use RoundlyConsulting\Certificates\Actions\RenewDueCertificatesAction;
use RoundlyConsulting\Certificates\DataTransferObjects\IssueCertificateData;
$certificate = app(IssueCertificateAction::class)->execute(
IssueCertificateData::make('shop.example.com'),
'tenant', // optional registry connection
);
$report = app(RenewDueCertificatesAction::class)->execute(7, queue: true, connection: 'tenant');Certificates::fake() swaps the container binding too, so constructor-injected managers are recorded like facade calls. Calling an action directly bypasses the manager — and with it the fake.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.