Skip to content

Rule-building API

Reference for constructing rules. Conceptual coverage is in Providing rules and The rule language.

The $schema parameter throughout is a Model instance, a WarrantSchema instance, a schema/model class-string, or a plain schema-key string.

public string $schemaKey;
public array $rules;
public function __construct(Model|WarrantSchema|string $schema, array $rules);
public static function fromSyntax(
Model|WarrantSchema|string $schema,
string $syntax,
array $bindings = [],
): self;
public static function fromRules(
Model|WarrantSchema|string $schema,
WarrantRule|WarrantRuleBuilder|array ...$rules,
): self; // flattens arrays; calls toRule() on builders; takes no bindings
public static function build(
Model|WarrantSchema|string $schema,
Closure $callback, // ($rule) => { $rule()->...; } — each call appends a rule
): self;
public function toSyntax(): string; // canonical DSL, inline literals
public function toBoundSyntax(): BoundSyntax; // DSL + a positional bindings array
public function validate(): void; // name-check against the registered schema
public static function validateAll(WarrantRuleSet|array ...$ruleSets): void;

validate() / validateAll() throw on the first unknown ability, condition, or context-key name — useful for CI-checking stored rules.

public ?IBooleanExpressionNode $conditions; // null = unconditional
public array $canAbilities;
public array $cannotAbilities;
public static function fromSyntax(string $syntax, array $bindings = []): self; // exactly one rule
public static function build(): WarrantRuleBuilder;
public function toSyntax(): string;
public function toBoundSyntax(): BoundSyntax;

fromSyntax throws if the string parses to zero or more than one rule.

Returned by WarrantRule::build(). Extends the condition builder with clause methods.

Condition methods (from WarrantConditionBuilder)

Section titled “Condition methods (from WarrantConditionBuilder)”

Each returns static and takes a condition name + parameters, or a closure (a parenthesized group):

->if(string|Closure $condition, array $parameters = [])
->andIf(...) // alias of if; both mean `and`
->orIf(...) // `or`
->ifNot(...) // `and not`
->andIfNot(...) // `and not`
->orIfNot(...) // `or not`
->ifRaw(string $expression, array $bindings = []) // splice a parsed DSL fragment as one group
->orIfRaw(string $expression, array $bindings = [])
->when(mixed $condition, Closure $callback): static // Laravel-style conditional
->theyCan(string ...$abilities): static // additive
->theyCannot(string ...$abilities): static // additive
->toRule(): WarrantRule // throws LogicException if no clause set
  • Precedence is not > and > or, identical to the DSL — the builder produces a byte-for-byte identical AST.
  • A closure is a parenthesized group and receives a bare WarrantConditionBuilder (no theyCan/theyCannot).
  • An empty group folds to false — nothing in an or, a veto in an and.
  • Condition parameters may be any PHP value — nothing is stringified.
public static function parse(string $source, array $bindings = []): array; // WarrantRule[]
public static function parseSingleRule(string $source, array $bindings = []): WarrantRule;
public static function parseConditionExpression(string $source, array $bindings = []): IBooleanExpressionNode;

toSyntax() and toBoundSyntax() render a rule back to the DSL and parse-back identically. toSyntax() can only render parameters that are expressible as inline literals (scalars); a parameter that’s an array, object, NAN, INF, or a float needing exponent notation throws a LogicException — use toBoundSyntax(), which extracts every parameter as a positional binding. @context references render as @context <key> in both forms and never consume a positional binding.