Skip to content

Update Redis::__construct options array shape#5952

Open
maryo wants to merge 3 commits into
phpstan:2.2.xfrom
maryo:patch-2
Open

Update Redis::__construct options array shape#5952
maryo wants to merge 3 commits into
phpstan:2.2.xfrom
maryo:patch-2

Conversation

@maryo

@maryo maryo commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
property change
retryInterval added (int)
readTimeout added (float)
persistent added (bool|string)
database added (int)
maxRetries added (int)
auth added |string variant

maryo added 3 commits June 29, 2026 20:41
┌───────────────┬───────────────────────┐
│   property    │        change         │
├───────────────┼───────────────────────┤
│ retryInterval │ added (int)           │
├───────────────┼───────────────────────┤
│ readTimeout   │ added (float)         │
├───────────────┼───────────────────────┤
│ persistent    │ added (bool|string)   │
├───────────────┼───────────────────────┤
│ database      │ added (int)           │
├───────────────┼───────────────────────┤
│ auth          │ added |string variant │
└───────────────┴───────────────────────┘
@maryo maryo changed the title Update Redis::__construct options parameter type Update Redis::__construct options array shape Jun 29, 2026
@staabm

staabm commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

thanks for the PR. where did you find documentation for such options?

@maryo

maryo commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

After updating PHPStan (perhaps it's config has been made more strict, too, i Rebased an older PR in our project), it started reporting that the database key was unknown.

I first checked the documentation at https://github.com/phpredis/phpredis#user-content-class-redis
It is fairly complete (but not formatted in the most readable way), but to be sure about the types, I checked out the source code and did an analysis using Claude. Two options are "missing" in the documentation:

  • maxRetries — not mentioned at all
  • backoff — present in the example but missing from the parameters list

And one thing is likely wrong:

  • retryInterval — docs say "milliseconds", but in the constructor path (redis_sock_configure) the value is stored directly via zval_get_long() without the ×1000 multiplication that connect() applies. So it's effectively microseconds, not milliseconds — contrary to what the docs say.

I didn't want to make the change too large, though, so I only added the keys that seemed most useful and added |string to auth.

This should be a more complete/strict array shape if interested, could be used instead:

array{
    host?: string,
    port?: int,
    connectTimeout?: float,
    readTimeout?: float,
    retryInterval?: int,
    persistent?: bool|string,
    database?: int,
    maxRetries?: int,
    auth?: string|array{string}|array{string|null, string},
    ssl?: array<string, mixed>,
    backoff?: array{algorithm?: int, base?: int, cap?: int},
}

host?: string
Hostname or Unix socket path. Strict IS_STRING check — any other type throws.

port?: int
Port number, defaults to 6379. Strict IS_LONG. Could be non-negative-int, but that might be too strict in practice.

connectTimeout?: float
Connection timeout in seconds, decimals preserved — stored via zval_get_double(). IS_LONG|IS_DOUBLE accepted; passing int is fine but float better communicates intent.

readTimeout?: float
Same semantics and C handling as connectTimeout.

retryInterval?: int
Reconnect delay. IS_LONG|IS_DOUBLE passes validation, but stored via zval_get_long() — decimals are silently truncated, so int is the honest type. Note: stored in microseconds here, unlike connect() where the same parameter is milliseconds (multiplied ×1000 in redis_sock_create). Could be non-negative-int, but that might be too strict in practice.

persistent?: bool|string
Non-string → zend_is_true() cast, enables persistence. String → used as persistent connection pool ID and implicitly enables persistence.

database?: int
Database index. C checks >= 0 && <= INT_MAX and throws on violation — non-negative-int would be accurate but might be too strict in practice.

maxRetries?: int
Max reconnect attempts. Same rationale as database.

auth?: string|array{string}|array{string|null, string}
Top-level check is IS_STRING|IS_ARRAY, anything else throws. Array elements go through redisTrySetAuthArg() which explicitly rejects IS_NULL|IS_FALSE — except null as username in the two-element form is valid (user stays NULL, only password is sent), useful when passing [$username, $password] against a legacy Redis without ACL.

ssl?: array<string, mixed>
Must be IS_ARRAY; stored as-is as a PHP stream context. Valid keys are whatever PHP's SSL stream wrapper accepts.

backoff?: array{algorithm?: int, base?: int, cap?: int}
algorithm maps to Redis::BACKOFF_ALGORITHM_* constants — C enforces range 0–6, values outside throw. Could be typed as int<0, 6> or Redis::BACKOFF_ALGORITHM_*, but int was chosen intentionally to keep the type less strict. base and cap are in milliseconds (internally ×1000 to µs) — could be non-negative-int, but that might be too strict in practice. Unknown keys emit E_WARNING and are ignored.

Or even more strict (the mentioned non-negative-int or the Redis::BACKOFF_ALGORITHM_*.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants