---
title: "Fluent builder — Certificates for Laravel | Roundly"
description: "Certificates::for() is the domain handle — set driver, SANs, owner, meta and validity, then issue, read status, or renew, revoke and expire."
url: https://roundly-consulting.com/open-source/docs/certificates-for-laravel/fluent-builder
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Certificates for Laravel](https://roundly-consulting.com/open-source/docs/certificates-for-laravel.md)

# Fluent builder

Certificates::for() returns a CertificateBuilder — the handle for one domain. Every setter returns the builder, so you describe the certificate and finish with a terminal call:

```php
use RoundlyConsulting\Certificates\Facades\Certificates;

$certificate = Certificates::for('shop.example.com')
    ->alsoFor('www.shop.example.com')
    ->using('acme')
    ->validForDays(90)
    ->meta(['tenant' => '7'])
    ->owner($tenant)        // attaches via the HasCertificates morph
    ->issue();
```

## Setters

| Method | Effect |
| --- | --- |
| `alsoFor(string ...$domains)` | Append SAN domains to one multi-domain certificate. |
| `using(string $driver)` | Driver for this issuance; also scopes find(), issueIfMissing(), status(), exists() and statusReport(). |
| `validForDays(int $days)` | Fallback expiry when the driver reports none (default 90). |
| `meta(array $meta)` | Stored in the registry’s meta JSON column. |
| `owner(Model $owner)` | Associates the certifiable owner. |
| `fresh(bool $fresh = true)` | Bypass the status cache for statusReport(). |

The issuer and namespace are driver configuration, not per-certificate options: the kubernetes driver always uses drivers.kubernetes.issuer, issuer\_kind and namespace. For a second issuer or namespace, register another driver with Certificates::extend() and pick it with using().

## Terminal methods

```php
$builder = Certificates::for('shop.example.com')->using('acme');

$builder->issue();                 // Certificate — always provisions
$builder->issueIfMissing();        // Certificate — the active certificate covering the domain, or a new issuance
$builder->exists();                // bool
$builder->status();                // ?CertificateStatus
$builder->find();                  // ?Certificate
$builder->fresh()->statusReport(); // ?CertificateStatusReport — cache bypassed

// Lifecycle verbs on the domain's registry row — the acme row only, because of using().
$builder->renew();                 // Certificate — renewed now
$builder->renewLater();            // Certificate — RenewCertificateJob queued
$builder->revoke('key compromise'); // Certificate — Revoked + CertificateRevoked
$builder->expire();                // Certificate — Expired + CertificateExpired
```

| Method | Returns | Behaviour |
| --- | --- | --- |
| `issue()` | Certificate | Always provisions and records. |
| `issueIfMissing()` | Certificate | Returns the active certificate already covering the domain — its own row, else a SAN certificate listing it — on the using() driver when set; otherwise issues. |
| `exists()` | bool | Asks the using() driver (or the default) about the primary domain. |
| `status()` | ?CertificateStatus | Registry status of the covering certificate (own row first, then SAN), on the using() driver when set. |
| `find()` | ?Certificate | Latest registry record for the primary domain, filtered by using(). |
| `statusReport()` | ?CertificateStatusReport | Live report from the using() driver (or the default), cache-aware. |
| `renew()` | Certificate | Renew the domain’s registry row now. |
| `renewLater()` | Certificate | Queue RenewCertificateJob for that row. |
| `revoke(?string $reason = null)` | Certificate | Record a revocation of that row. |
| `expire()` | Certificate | Mark that row expired. |

The lifecycle verbs resolve the domain’s most recent registry row — on the using() driver when set — and call the matching manager method, so Certificates::fake() records them. No row throws CertificateException; the handle never falls back to another domain’s row, or to the same domain’s row under another driver.

for() also accepts a list of domains — the first is the primary, the rest become SANs (see Multi-domain & wildcards). Build the handle with Certificates::for() — its constructor is internal. Like the manager, the builder is macroable.

## 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 crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/certificates-for-laravel.md)
