Skip to content

Arg

Rasuvaeff\Understudy\Arg

ClassPackage: rasuvaeff/understudySourceVersion: v0.4.1

Argument matchers, usable only inside a specification closure:

php
when(fn () => $repository->find(Arg::any()))->returns($book);

Every matcher is declared to return mixed rather than the internal ArgumentMatcher type. That is not vagueness — it is what the matcher means. A matcher stands in for a value of whatever type the parameter declares, and it is never consumed as a value: the runtime intercepts it while recording the call specification. Declaring the concrete class instead would make find(Arg::any()) a type error in every IDE and analyser for a contract that says find(int $id), on the first line of the first example anyone copies — while mixed is accepted everywhere and stays honest.

understudy-psalm narrows this to the parameter's declared type, so users of the plugin get a real check rather than mixed.

Methods

any()

php
static any(): mixed

Matches any argument, including null.

int()

php
static int(?int $min = NULL, ?int $max = NULL): mixed

Matches an int, optionally within bounds. A numeric string does not match: the matcher pins the declared type as well as the value.

float()

php
static float(?float $min = NULL, ?float $max = NULL): mixed

Matches a float, optionally within bounds. An int does not match.

string()

php
static string(non-empty-string|null $matches = NULL): mixed

Matches a string, optionally against a PCRE pattern.

  • $matches — delimiters included, e.g. /^ord-/

bool()

php
static bool(): mixed

same()

php
static same(mixed $value): mixed

Strict identity — for objects, the very same instance.

not()

php
static not(mixed $value): mixed

Negates a literal or another matcher: not(5), not(Arg::instanceOf(…)).

allOf()

php
static allOf(mixed $operands): mixed

Matches an argument every operand accepts. An operand is a matcher or a literal, the same pair not() takes.

  • $operands — at least one; a tail matcher is not one of them

anyOf()

php
static anyOf(mixed $operands): mixed

Matches an argument at least one operand accepts. With literals it reads as a set: anyOf('draft', 'review').

  • $operands — at least one; a tail matcher is not one of them

instanceOf()

php
static instanceOf(class-string $type): mixed

captor()

php
static captor(class-string<\T>|null $class = NULL): Captor

A typed argument captor. Its capture() goes where the argument to observe goes, matches like instanceOf() — or like any() for the untyped form — and records the value once the whole specification matched:

php
$options = Arg::captor(DeliveryOptions::class);
when(fn () => $store->temporaryUrl(Arg::any(), Arg::any(), $options->capture()))
    ->returns('https://…');

$subject->run();

$options->last();   // DeliveryOptions, typed
$options->all();    // list<DeliveryOptions>, in call order

The typed replacement for reading args[N] out of the call log: last() and all() carry the class through, so no instanceof narrowing ritual is needed at the read site.

satisfies()

php
static satisfies(
    callable $predicate,
    non-empty-string $description = 'satisfies(…)',
): mixed

Matches whatever the predicate accepts.

  • $description — shown in failure messages

containing()

php
static containing(array<array-key,mixed> $entries): mixed

Matches an array containing these entries and possibly more: a list by value, a map by key and value.

count()

php
static count(int<0, max>|null $minimum = NULL, int<0, max>|null $maximum = NULL): mixed

Matches an array or Countable whose size is within bounds.

which()

php
static which(non-empty-string $method, mixed $value): mixed

Matches an object whose getter answers this value.

  • $method — public, non-static, no required arguments

none()

php
static none(): mixed

Requires the variadic tail to be empty. Only valid as the last argument.

remaining()

php
static remaining(): mixed

Matches the whole variadic tail, of any length including none. Only valid as the last argument.

rest()

php
static rest(): mixed

"The arguments before this one matter, the rest of the arity does not." Only valid as the last argument, and the one matcher that lets a specification stop before the method's required parameters run out:

php
when(fn () => $storage->recordOutcome('svc', Arg::rest()))
    ->throws(new RuntimeException('storage unavailable'));

The distinction from remaining(): remaining() stands for the variadic tail a method declares; rest() stands for declared parameters the specification chose not to spell out. A later, narrower specification for the same call still wins over the broad prefix stub, the way overlapping matchers already compose.