Version: 1.0 Date: 2024-02-05 Applies to: KaririCode\Dotenv 4.1+
KaririCode\Dotenv provides two validation mechanisms:
- Fluent DSL — Programmatic rule definition via
EnvironmentValidator. - Schema file — Declarative rule definition via
.env.schema(see SPEC-005).
Both mechanisms collect all failures before throwing a single ValidationException.
$dotenv->required('DB_HOST', 'DB_PORT', 'APP_ENV');Throws ValidationException listing all missing variables.
$dotenv->validate() // Returns EnvironmentValidator
->required(...)
->isInteger(...)
->assert(); // Executes all rules, throws on failure$dotenv->loadWithSchema(__DIR__ . '/.env.schema');Parses the schema, loads .env if not already loaded, applies rules, and asserts.
These methods set the current target variables for subsequent rule methods.
| Method | Behavior |
|---|---|
required(string ...$names): self |
Marks variables as required (must exist). Sets targets. |
ifPresent(string ...$names): self |
Sets targets. Rules only apply if variable exists. |
Rule methods apply their rule to the current targets (set by the most recent targeting method or rule method that accepts names).
| Method | Rule Applied | Target Behavior |
|---|---|---|
notEmpty(string ...$names) |
NotEmptyRule |
If $names given, sets new targets; otherwise uses current. |
isInteger(string ...$names) |
IsIntegerRule |
Same. |
isBoolean(string ...$names) |
IsBooleanRule |
Same. |
isNumeric(string ...$names) |
IsNumericRule |
Same. |
between(int|float $min, int|float $max) |
BetweenRule |
Always uses current targets (chainable). |
allowedValues(string $name, array $allowed) |
AllowedValuesRule |
Sets target to [$name]. |
matchesRegex(string $name, string $pattern) |
MatchesRegexRule |
Sets target to [$name]. |
url(string ...$names) |
UrlRule |
If $names given, sets new targets. |
email(string ...$names) |
EmailRule |
Same. |
custom(string $name, Closure $callback, string $message) |
CustomRule |
Sets target to [$name]. |
rule(ValidationRule $rule, string ...$names) |
Arbitrary rule | If $names given, sets new targets. |
Methods that inherit current targets enable natural chains:
->isInteger('DB_PORT')->between(1, 65535)
// isInteger sets target to ['DB_PORT']
// between inherits target ['DB_PORT']public function assert(): void- Checks all
requiredvariables for presence. - Iterates all variables with registered rules.
- Skips absent variables in conditional mode (
ifPresent). - Skips absent required variables from rule execution (already reported as missing).
- Collects all failure messages.
- Throws
ValidationException::batchErrors($errors)if any failures exist.
trim($value) !== ''Message: "{name} must not be empty."
preg_match('/\A[+-]?\d+\z/', $value) === 1Message: "{name} must be an integer."
Accepted values (case-insensitive): true, false, 1, 0, yes, no, on, off.
Message: "{name} must be a boolean (true/false, yes/no, on/off, 1/0)."
is_numeric($value)Message: "{name} must be numeric."
is_numeric($value) && ($value + 0) >= $min && ($value + 0) <= $maxMessage: "{name} must be between {min} and {max}."
in_array($value, $allowed, strict: true)Message: "{name} must be one of: {comma-separated list}."
preg_match($pattern, $value) === 1Message: "{name} must match pattern {pattern}."
filter_var($value, FILTER_VALIDATE_URL) !== falseMessage: "{name} must be a valid URL."
filter_var($value, FILTER_VALIDATE_EMAIL) !== falseMessage: "{name} must be a valid email address."
User-provided Closure(string): bool with custom message.
Message: User-defined (default: "{name} failed custom validation.")
interface ValidationRule
{
public function passes(string $value): bool;
public function message(): string;
}The {name} placeholder in message() is replaced with the variable name at assertion time.
final readonly class MinLengthRule implements ValidationRule
{
public function __construct(private int $minLength) {}
public function passes(string $value): bool
{
return strlen($value) >= $this->minLength;
}
public function message(): string
{
return "{name} must be at least {$this->minLength} characters.";
}
}
$dotenv->validate()
->rule(new MinLengthRule(32), 'API_KEY')
->assert();final class ValidationException extends DotenvException
{
public static function missingRequired(array $missing): self;
public static function batchErrors(array $errors): self;
public static function schemaViolation(string $message): self;
/** @return list<string> All failure messages. */
public function errors(): array;
}The errors() method returns a flat list of failure messages, suitable for display in logs or CLI output.
The EnvironmentValidator receives a Closure(string): ?string that resolves variable names to raw string values. This decouples validation from the storage mechanism:
new EnvironmentValidator(
fn (string $name): ?string => $this->resolveRawValue($name),
);Resolution order inside resolveRawValue(): $this->variables[$name]->rawValue → $_ENV[$name] → $_SERVER[$name] → null.
Validation operates on raw string values, not typed values. This ensures that isInteger('DB_PORT') validates the string "5432", not the integer 5432.