- feat(type): add
numerictype - #793 by @gsteel
- fix(http-client): validate all
Transfer-Encodingresponse fields and reject invalid or unsupported transfer codings instead of falling back toContent-Length- #806
- fix(h2): validate
content-lengthheader against received DATA on server connections, preventing HTTP/2 request smuggling onPsl\H2\ServerConnection(GHSA-pw9p-jvrm-f7rm)
- feat(either-or-both): introduce
EitherOrBothcomponent - a three-variant disjoint union (Left/Right/Both) for values that may be present on either or both of two sides, inspired by Rust'sitertools::EitherOrBothand Haskell'sData.These. Primary use case: three-way diff of two collections (insert / delete / update events). Secondary: layered config merge, multi-source enrichment, dual-validation, snapshot comparison. Fullmap/mapLeft/mapRight/mapAny/swap/proceed/apply/containsLeft/containsRightsurface;left()/right()/both()free constructors. - feat(iter): add
Iter\merge_join_byandIter\merge_join_by_key- full-outer-join stream producers that yieldEitherOrBothevents as a rewindableIter\Iterator.merge_join_byis a lazy two-cursor merge over sorted inputs (O(1) memory on first traversal,Psl\Comparison\Order-returning comparator, matching Rust'sitertools::merge_join_by);merge_join_by_keyis a hash-based variant for keyed inputs that do not need to be pre-sorted (O(|right|) memory). - feat(io): add
IO\IterableReadHandle- a streamingReadHandleInterfacethat lazily consumes aniterable<string>without buffering the entire content in memory - feat(io): add
IO\ConcatReadHandle- reads from two handles in sequence, switching to the second when the first reaches EOF - feat(io): add
IO\JoinedReadWriteHandle- joins aReadHandleInterfaceandWriteHandleInterfaceinto a single read-write handle, delegating all operations to the respective underlying handle - feat(io): add
IO\TeeWriteHandle- writes to two handles simultaneously with backpressure buffering when the second handle is slower - feat(io): add
IO\SinkWriteHandle- a/dev/null-like write handle that discards all written data - feat(io): add
IO\SinkReadHandle- a read handle that is always at EOF, unlikeMemoryHandle('')which only reports EOF after the first read - feat(io): add
IO\SinkReadWriteHandle- a sink that discards writes and always reports EOF on reads - feat(io): add
IO\TruncatedReadHandle- reads up to N bytes from an underlying handle, silently reporting EOF when the limit is reached - feat(io): add
IO\BoundedReadHandle- reads up to N bytes from an underlying handle, throwingRuntimeExceptionif the underlying handle has more data than the limit allows - feat(io): add
IO\FixedLengthReadHandle- reads exactly N bytes from an underlying handle, throwingRuntimeExceptionon premature EOF - feat(io): add
IO\copy_chunked()andIO\copy_bidirectional_chunked()- variants ofIO\copy()andIO\copy_bidirectional()that accept a custom chunk size - feat(http-client): add
SendConfiguration::$connectionTimeout- per-request maximum duration for establishing a connection (TCP + TLS handshake), using a linked cancellation token - feat(type): support
'true'/'false'string literals inType\bool()coercion - #735 by @verweto - feat(mime): introduce
MIMEcomponent - comprehensive MIME toolkit implementing RFC 2045-2049 and related standards- Media type parsing, validation, and content negotiation (
MediaType,MediaRange,MediaPreferences) per RFC 2045, RFC 6838, RFC 9110 - MIME part construction with automatic transfer encoding (
Part\Text,Part\Data) per RFC 2045 - Streaming multipart body construction and parsing (
MultiPart\Composite,MultiPart\Alternative,MultiPart\Related,MultiPart\Form,MultiPart\Parser) per RFC 2046, RFC 2387, RFC 7578 - Immutable header collection with RFC 5322 line folding (
Headers) - Content-Disposition parsing with safe filename extraction (
ContentDisposition) per RFC 2183 - Content-ID parsing, generation, and
cid:URI support (ContentId) per RFC 2392 - RFC 2231 parameter encoding/decoding with continuations and charset conversion (
Parameters) - Content sniffing from bytes and seekable handles (
Sniff\from_string,Sniff\from_handle) - S/MIME signing, verification, encryption, and decryption (
SMIME\Signer,SMIME\Verifier,SMIME\Encryptor,SMIME\Decryptor) per RFC 5652, RFC 8551 - DKIM message signing with RSA-SHA256 and Ed25519-SHA256 (
DKIM\Signer) per RFC 6376, RFC 8301, RFC 8463
- Media type parsing, validation, and content negotiation (
- feat(message): introduce
Messagecomponent - RFC 5322 internet message construction, parsing, and serialization- Typed header fields with fluent
with*()methods (Message) per RFC 5322 - Address methods accept
string|Mailbox|AddressListfor convenience - Message body as
PartInterfacefrom the MIME component per RFC 2045 - Streaming
serialize()andparse()accepting string orReadHandleInterface - Reply, reply-all, and forward with automatic threading headers (In-Reply-To, References) per RFC 5322
- SMTP envelope derivation (
Envelope) per RFC 5321 - RFC 5322 address parsing:
Mailbox,Group,AddressListwith RFC 2047 encoded-word support
- Typed header fields with fluent
- feat(smtp): introduce
SMTPcomponent - RFC 5321 SMTP client with connection pooling, TLS, and authentication- Low-level
ConnectionimplementingNetwork\StreamInterfacefor protocol-level SMTP operations - High-level
Transportmanaging the full SMTP lifecycle: connect, EHLO/HELO, STARTTLS, AUTH, send, RSET - Connection pooling with automatic reuse across multiple sends via
TCP\SocketPool - Implicit TLS (port 465) and STARTTLS upgrade (RFC 3207) with automatic detection
- EHLO with HELO fallback per RFC 5321
- SMTP pipelining (RFC 2920) for reduced round-trips
- BDAT chunking (RFC 3030) to avoid dot-stuffing overhead on large messages
- Enhanced status codes (RFC 3463) with structured
EnhancedStatusCodeparsing - DSN delivery status notifications (RFC 3461) via
SendConfiguration - REQUIRETLS (RFC 8689) for end-to-end TLS enforcement
- MT-PRIORITY (RFC 6710) message priority with STANAG 4406 levels
- DELIVERBY (RFC 2852) delivery deadline specification
- FUTURERELEASE (RFC 4865) deferred delivery via
DurationorDateTimeInterface - BINARYMIME (RFC 3030), 8BITMIME (RFC 6152), SMTPUTF8 (RFC 6531) capability negotiation
- Punycode IDN encoding for internationalized domain names in addresses
- Partial recipient success with
DeliveryReportfor per-recipient rejection tracking - CRLF and null byte injection protection via
PossibleAttackException - Five authentication mechanisms: PLAIN (RFC 4616), LOGIN, XOAUTH2, CRAM-MD5 (RFC 2195), SCRAM-SHA-256 (RFC 7677)
- Immutable
TransportConfigurationandSendConfigurationwith fluentwith*()builders - Configurable pipelining, chunking, chunk size, and partial success behavior
- Low-level
- feat(dns): introduce
DNScomponent - async DNS resolution with full protocol supportSystemResolvermirrors OS DNS behavior, usable as a default parameter value- UDP and pooled TCP resolvers with automatic TCP fallback on truncation
- DNS-over-TLS (DoT) via TLS client configuration on
TCPResolver RacingResolverraces multiple nameservers concurrently for fastest responseSplitHorizonResolverroutes queries by domain name for split-horizon DNSSearchDomainResolverexpands short names using search domain listsHostsFileResolverchecks the OS hosts file before network queriesCachedResolverdecorator with TTL-aware caching viaCache\StoreInterfaceStaticResolverfor hardcoded records in tests and development- Cross-platform system configuration loading (Linux, macOS, Windows) via async process execution
- EDNS0 support: DNS cookies, client subnet, padding, NSID, TCP keepalive, key tag, extended DNS error
- 20+ record types: A, AAAA, NS, CNAME, MX, TXT, SRV, SOA, PTR, CAA, SSHFP, TLSA, SVCB, HTTPS, LOC, NAPTR, DS, DNSKEY, RRSIG, NSEC, NSEC3
- DNS-over-HTTPS (DoH) via
HTTPSResolverusing the HTTP client (RFC 8484) - DNS name validation with null byte and label length enforcement
ResponseCodehelper methods:isSuccess(),isError(),isServerError(),isNameError()
- feat(dnssec): introduce
DNSSECcomponent - full DNSSEC validation chainSecureResolvervalidates RRSIG signatures on every responseTrustChainResolverwalks DS/DNSKEY chain from root to target zoneCachedTrustChainResolvercaches trust chain results for performanceStaticTrustChainResolverfor offline/air-gapped environments- NSEC and NSEC3 authenticated denial of existence proof validation
- 7 signature algorithms: RSA/SHA-1, RSA/SHA-256, RSA/SHA-512, ECDSA P-256, ECDSA P-384, Ed25519, Ed448
- 4 specific validation exceptions:
SignatureFailedException,BrokenTrustChainException,InvalidProofException,UnsignedResponseException
- feat(http-message): introduce
HTTP Messagecomponent - version-agnostic HTTP message abstractionsRequestandResponseimmutable value objects with streaming body (ReadHandleInterface)FieldMapordered, case-insensitive header field collection with lazy indexProtocolVersionenum covering HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3- Trailers modelled as
Async\Awaitable<FieldMap>for HTTP/2 and chunked HTTP/1.1 - HTTP status code and method constants per RFC 9110
reason_phrase()function for HTTP/1.x status line serialization- Fluent
with*()mutation methods on both Request and Response Transactiongroups the final response with informational (1xx) responses and server push exchangesExchangerepresents a pushed request/response pair for HTTP/2 server push
- feat(http-client): introduce
HTTP Clientcomponent - async HTTP/1.1 and HTTP/2 client with connection poolingClientwith automatic protocol negotiation via ALPN (HTTP/2 preferred, HTTP/1.1 fallback)PooledConnectorwith HTTP/1.x idle connection reuse and HTTP/2 session sharing across concurrent requests- HTTP/2 multiplexing with event-driven stream dispatch via
H2Multiplexerand per-streamH2Streamstate - Transparent reconnection on connection failure (GOAWAY, TCP reset) via pool-backed reconnect closures
RedirectClientdecorator following 301/302/303/307/308 redirects with method rewriting per RFC 9110, cross-origin credential stripping, and auto-referrerRetryClientdecorator with configurable exponential backoff and jitter for transport-level failuresSendConfigurationfor per-request overrides (body size limits, TLS, protocol versions, tunnel) merged withClientConfigurationdefaultsDeniedDestinationsMiddlewarefor SSRF protection against private IP ranges (RFC 1918, RFC 4193, loopback, link-local)- Connection-level middleware via
HandlerInterface/MiddlewareInterfacechain with access to peer address and TLS state - SOCKS5 proxy support via
ClientConfiguration::$proxyusingPsl\Socks\Connector - HTTP CONNECT tunnel support via
ClientConfiguration::$tunnelwith TLS and proxy authentication noTunnelinghost bypass rules (exact match, domain suffix, wildcard)- H2 flow control with BDP auto-tuning for dynamic receive window sizing
- Lazy, pull-based response body reading via
ResponseBodyHandleimplementingReadHandleInterface - 104 integration tests against httpbun covering methods, redirects, auth, caching, cookies, concurrency, and streaming
- feat(h2): introduce unified
Configurationreplacing deprecatedClientConfigurationandServerConfiguration- Both
ClientConnectionandServerConnectionnow acceptConfigurationin addition to their legacy config types ClientConnectionnow supports BDP auto-tuning when usingConfigurationwithmaxReceiveWindowSizeset
- Both
- feat(tcp): add
bindTooption toConnectConfigurationfor binding to a specific local address before connecting - feat(tcp): add
bindTooption toListenConfigurationfor binding to a specific local address before listening - feat(tcp): add
withBindTo()fluent builder method to bothConnectConfigurationandListenConfiguration - feat(tcp):
connect()now respectsConnectConfiguration::$bindToby setting thesocket.bindtostream context option - feat(type): Allow null argument to
Type\class_stringto assert or coerce bareclass-string
- chore(types): annotate read-only template parameters with
@template-covariantacross the library, allowing values to flow into wider declarations:Async\Awaitable<T>,Promise\PromiseInterface<T>Result\ResultInterface<T>,Result\Success<T>,Result\Failure<T, Te>Option\Option<T>Either\Either<TLeft, TRight>,Either\Left<TLeft>,Either\Right<TRight>Tree\NodeInterface<T>,Tree\LeafNode<T>,Tree\TreeNode<T>
- chore(collection): annotate immutable collection template parameters with
@template-covariant(CollectionInterface,AccessibleCollectionInterface,IndexAccessInterface,MapInterface,Map,SetInterface,Set,VectorInterface,Vector); mutable collections remain invariant. - chore(async): annotate
Sequence,KeyedSequence,Semaphore,KeyedSemaphoretemplate parameters with the correct variance; keys/inputs are@template-contravariant(write-position only) and outputs are@template-covariant(read-position only). - chore(collection): relax
Vector::getIterator()andMutableVector::getIterator()return type fromIterator<int<0, max>, T>toIterator<int, T>.
- fix(io):
IO\copy()now flushes the writer after copying if it implementsBufferedWriteHandleInterface, ensuring no data remains in an internal buffer - fix(async):
State::subscribe()andState::invokeCallbacks()no longer capture$thisin queued closures, preventing delayed garbage collection ofDeferred/Awaitablechains - fix(uri): bare IPv6 addresses (e.g.,
http://::1/path) are now correctly parsed asIPHostinstead of being misparsed as a registered name with a numeric port - fix(h2): separate
maxConcurrent(peer's limit on our streams) frompeerMaxConcurrent(our limit on peer's streams) inStreamTable, preventing the client's own SETTINGS from limiting its outgoing streams - fix(h2):
BDPEstimatornow produces an initial connection-level WINDOW_UPDATE duringinitialize()to bring the receive window from the RFC default (65535) up toinitialWindowSize, preventing flow-control stalls when many concurrent streams receive data simultaneously - fix(h2):
notifyWindowWaiters()now copies the waiter list before iterating and properly removes satisfied waiters, preventing iteration corruption and memory leaks - fix(io):
ResourceHandlereadable/writable callbacks now null out the suspension reference before callingresume(), preventing "Must call suspend() before calling throw()" errors during handle destruction - fix(io):
ResourceHandle::doRead()anddoWrite()cancellation subscriptions now null out the suspension reference before throwing, preventing double-wake when cancellation and close race during PHP shutdown - fix(encoding): RFC 2047 encoded-word encoder no longer embeds CRLF line folding in the encoded output; line folding is now the responsibility of the header serializer, fixing header/body separation issues in serialized messages
- deprecated(tcp):
Socketclass -- useConnectConfiguration::$bindToorListenConfiguration::$bindToinstead. Will be removed in PSL 7.0. - deprecated(h2):
ClientConfiguration-- useConfigurationinstead. Will be removed in PSL 7.0. - deprecated(h2):
ServerConfiguration-- useConfigurationinstead. Will be removed in PSL 7.0.
- ci: add httpbun, microsocks, and tinyproxy services to unit-tests, code-coverage, mutation-tests, and package-tests workflows for HTTP client integration testing
- fix(str):
Str\chr()now throwsOutOfBoundsExceptionfor invalid Unicode code points instead of silently returning an empty string - fix(str):
Str\from_code_points()now validates code points and throwsOutOfBoundsExceptionfor out-of-range values, surrogates, and negative inputs instead of producing invalid UTF-8; implementation now delegates toStr\chr()for consistent behavior
- chore(str): clarify
width(),truncate(), andwidth_slice()PHPDoc to explicitly referencemb_strwidth()/mb_strimwidth()semantics - chore: make all function calls explicit across the codebase, eliminating PHP namespace fallback resolution
- chore(h2): skip timer-sensitive rate limiter test on Windows
- feat(io): introduce
Psl\IO\BufferedWriteHandleInterface, extendingWriteHandleInterfacewithflush()for handles that buffer data internally before writing to an underlying resource - feat: introduce
Compressioncomponent with streaming compression/decompression abstractions for IO handles. ProvidesCompressorInterface,DecompressorInterface, four handle decorators (CompressingReadHandle,CompressingWriteHandle,DecompressingReadHandle,DecompressingWriteHandle), and convenience functionscompress()anddecompress() - feat: introduce
HPACKcomponent - RFC 7541 HPACK header compression for HTTP/2 - feat: introduce
H2component - HTTP/2 binary framing protocol implementation - feat: introduce
Cachecomponent - async-safe in-memory LRU cache with per-key atomicity viaKeyedSequence, proactive TTL expiration via event loop
- fix(io):
Reader::readUntil()andReader::readUntilBounded()no longer treat empty reads from non-blocking streams as EOF, fixingreadLine()returning the entire content instead of individual lines when used with non-blocking streams - fix(docs): source links now correctly point to
packages/{name}/src/Psl/instead of the non-existent top-levelsrc/Psl/path - internal: add
splitter auditcommand to verify organization repository settings (wiki, issues, discussions, PRs, tag immutability).
- BC - All
null|Duration $timeoutparameters across IO, Network, TCP, TLS, Unix, UDP, Socks, Process, and Shell components have been replaced withCancellationTokenInterface $cancellation = new NullCancellationToken(). This enables both timeout-based and signal-based cancellation of async operations. - BC - Removed
Psl\IO\Exception\TimeoutException- usePsl\Async\Exception\CancelledExceptioninstead. - BC - Removed
Psl\Network\Exception\TimeoutException- usePsl\Async\Exception\CancelledExceptioninstead. - BC - Removed
Psl\Process\Exception\TimeoutException- usePsl\Async\Exception\CancelledExceptioninstead. - BC - Removed
Psl\Shell\Exception\TimeoutException- usePsl\Async\Exception\CancelledExceptioninstead. - BC -
Psl\IO\CloseHandleInterfacenow requires anisClosed(): boolmethod. - BC -
Network\SocketInterface::getLocalAddress()andNetwork\StreamInterface::getPeerAddress()no longer throw exceptions. Addresses are resolved at construction time and cached, making these O(1) property lookups with no syscall. - BC -
BufferedReadHandleInterface::readLine()now always splits on"\n"instead ofPHP_EOL. Trailing"\r"is stripped, so both"\n"and"\r\n"line endings are handled consistently across all platforms. UsereadUntil(PHP_EOL)for system-dependent behavior. - BC -
Psl\TLS\ServerConfigrenamed toPsl\TLS\ServerConfiguration. - BC -
Psl\TLS\ClientConfigrenamed toPsl\TLS\ClientConfiguration. - BC - All variables and parameters across the codebase now use
$camelCasenaming instead of$snake_case. - BC -
TCP\listen(),TCP\connect(),TCP\Socket::listen(),TCP\Socket::connect()now accept configuration objects (TCP\ListenConfiguration,TCP\ConnectConfiguration) instead of individual parameters for socket options. - BC -
Unix\listen()andUnix\Socket::listen()now acceptUnix\ListenConfigurationinstead of individual parameters. - BC -
UDP\Socket::bind()now acceptsUDP\BindConfigurationinstead of individual parameters. - BC -
TCP\Socketsetter/getter methods (setReuseAddress,setReusePort,setNoDelay, etc.) have been removed. Use configuration objects instead. - BC -
TCP\Connectorconstructor now acceptsTCP\ConnectConfigurationinstead ofbool $noDelay. - BC -
Socks\Connectorconstructor changed from(string $proxyHost, int $proxyPort, ?string $username, ?string $password, ConnectorInterface $connector)to(ConnectorInterface $connector, Socks\Configuration $configuration). - BC - Renamed
ingoingtoongoingacrossSemaphore,Sequence,KeyedSemaphore, andKeyedSequence(hasIngoingOperations()->hasOngoingOperations(),getIngoingOperations()->getOngoingOperations(), etc.).
- feat(async): introduce
Psl\Async\CancellationTokenInterfacefor cancelling async operations - feat(async): introduce
Psl\Async\NullCancellationToken- no-op token used as default parameter value - feat(async): introduce
Psl\Async\SignalCancellationToken- manually triggered cancellation viacancel(?Throwable $cause) - feat(async): introduce
Psl\Async\TimeoutCancellationToken- auto-cancels after aDuration, replacing the oldDuration $timeoutpattern - feat(async): introduce
Psl\Async\LinkedCancellationToken- cancelled when either of two inner tokens is cancelled, useful for combining a request-scoped token with an operation-specific timeout - feat(async): introduce
Psl\Async\Exception\CancelledException- thrown when a cancellation token is triggered; the cause (e.g.,TimeoutException) is attached as$previous. Use$e->getToken()to identify which token triggered the cancellation. - feat(async):
Async\sleep()now accepts an optionalCancellationTokenInterfaceparameter, allowing early wake-up on cancellation - feat(async):
Awaitable::await()now accepts an optionalCancellationTokenInterfaceparameter - feat(async):
Sequence::waitFor()andSequence::waitForPending()now accept an optionalCancellationTokenInterfaceparameter - feat(async):
Semaphore::waitFor()andSemaphore::waitForPending()now accept an optionalCancellationTokenInterfaceparameter - feat(async):
KeyedSequence::waitFor()andKeyedSequence::waitForPending()now accept an optionalCancellationTokenInterfaceparameter - feat(async):
KeyedSemaphore::waitFor()andKeyedSemaphore::waitForPending()now accept an optionalCancellationTokenInterfaceparameter - feat(channel):
SenderInterface::send()andReceiverInterface::receive()now accept an optionalCancellationTokenInterfaceparameter - feat(network):
ListenerInterface::accept()now accepts an optionalCancellationTokenInterfaceparameter - feat(tcp):
TCP\ListenerInterface::accept()now accepts an optionalCancellationTokenInterfaceparameter - feat(unix):
Unix\ListenerInterface::accept()now accepts an optionalCancellationTokenInterfaceparameter - feat(tls):
TLS\Acceptor::accept(),TLS\LazyAcceptor::accept(),TLS\ClientHello::complete(), andTLS\Connector::connect()now accept an optionalCancellationTokenInterfaceparameter - cancellation propagates through the TLS handshake - feat(tls):
TLS\TCPConnector::connect()andTLS\connect()now pass the cancellation token through to the TLS handshake - feat(async): introduce
Psl\Async\TaskGroupfor running closures concurrently and awaiting them all withdefer()+awaitAll() - feat(async): introduce
Psl\Async\WaitGroup, a counter-based synchronization primitive withadd(),done(), andwait() - feat(encoding): introduce
Psl\Encoding\QuotedPrintable\encode(),decode(), andencode_line()for RFC 2045 quoted-printable encoding with configurable line length and line ending - feat(encoding): introduce
Psl\Encoding\EncodedWord\encode()anddecode()for RFC 2047 encoded-word encoding/decoding in MIME headers (B-encoding and Q-encoding with automatic selection) - feat(tls): introduce
TLS\ListenerInterfaceandTLS\Listener, wrapping anyNetwork\ListenerInterfaceto perform TLS handshakes on accepted connections - feat(encoding): add
Base64\Variant::Mimefor RFC 2045 MIME Base64 with 76-char line wrapping and CRLF, using constant-time encoding/decoding - feat(encoding): introduce streaming IO handles for Base64 (
EncodingReadHandle,DecodingReadHandle,EncodingWriteHandle,DecodingWriteHandle), QuotedPrintable (same 4), and Hex (same 4), bridgingPsl\IOandPsl\Encodingfor transparent encode/decode on read/write - feat(io): introduce
Psl\IO\BufferedReadHandleInterface, extendingReadHandleInterfacewithreadByte(),readLine(),readUntil(), andreadUntilBounded() - feat(io):
Psl\IO\Readernow implementsBufferedReadHandleInterface - feat(tcp): introduce
TCP\ListenConfigurationandTCP\ConnectConfigurationwith immutablewith*builder methods - feat(unix): introduce
Unix\ListenConfigurationwith immutablewith*builder methods - feat(udp): introduce
UDP\BindConfigurationwith immutablewith*builder methods - feat(socks): introduce
Socks\Configurationwith immutablewith*builder methods for proxy host, port, and credentials - feat(tcp): introduce
TCP\RestrictedListener, wrapping a listener to restrict connections to a set of allowedIP\AddressandCIDR\Blockentries - feat(network): introduce
Network\CompositeListener, accepting connections from multiple listeners concurrently through a singleaccept()call - feat: introduce
URIcomponent - RFC 3986 URI parsing, normalization, reference resolution, and RFC 6570 URI Template expansion (Levels 1–4), with RFC 5952 IPv6 canonical form and RFC 6874 zone identifiers - feat: introduce
IRIcomponent - RFC 3987 Internationalized Resource Identifier parsing with Unicode support, RFC 3492 Punycode encoding/decoding, and RFC 5891/5892 IDNA 2008 domain name processing - feat: introduce
URLcomponent - strict URL type with scheme and authority validation, default port stripping for known schemes, and URI/IRI conversion - feat: introduce
Punycodecomponent - RFC 3492 Punycode encoding and decoding for internationalized domain names - fix(tcp):
RetryConnectorbackoff sleep now respects cancellation tokens, allowing retry loops to be cancelled during the delay - fix(io, str):
IO\write(),IO\write_line(),IO\write_error(),IO\write_error_line(), andStr\format()no longer pass the message throughsprintf/vsprintfwhen no arguments are given, preventing format string errors when the message contains%characters
Replace Duration timeout parameters with TimeoutCancellationToken:
// Before (5.x)
$data = $reader->read(timeout: Duration::seconds(5));
// After (6.0)
$data = $reader->read(cancellation: new Async\TimeoutCancellationToken(Duration::seconds(5)));For manual cancellation (e.g., cancel all request IO when a client disconnects):
$token = new Async\SignalCancellationToken();
// Pass to all request-scoped IO
$body = $reader->readAll(cancellation: $token);
// Cancel from elsewhere
$token->cancel();- feat(io): added
Reader::readUntilBounded(string $suffix, int $max_bytes, ?Duration $timeout)method, which reads until a suffix is found, but throwsIO\Exception\OverflowExceptionif the content exceeds$max_bytesbefore the suffix is encountered - #620 - by @azjezz - feat(io): added
IO\Exception\OverflowExceptionexception class - #620 - by @azjezz - feat(type): add
Type\json_decoded()type for transparent JSON string coercion - #619 by @veewee - feat(type): add
Type\nullish()type for optional-and-nullable shape fields - #618 by @veewee
- feat(dict, vec): add filter_nonnull_by and map_nonnull - #576 by @Dima-369
- feat(tcp): add
backlogparameter toTCP\listen()for configuring the pending connection queue size - #617 - by @azjezz - feat(tcp): listener now drains the accept backlog in a loop for higher throughput - #617 - by @azjezz
- chore: update dev dependencies, and re-format the codebase using latest mago version - #616 by @azjezz
- feat(io): introduce
IO\spool()for memory-backed handles that spill to disk
- feat: introduce
IPcomponent with immutable, binary-backedAddressvalue object andFamilyenum - feat(cidr):
CIDR\Block::contains()now acceptsstring|IP\Address
- feat(tls): introduce
TLS\TCPConnectorfor poolable TLS connections - feat(tls):
TLS\StreamInterfacenow extendsTCP\StreamInterface, enabling TLS streams to be used withTCP\SocketPoolInterface
- Dropped PHP 8.3 support; minimum is now PHP 8.4 - #584 by @azjezz
- Migrated to PHPUnit 13 - #584 by @azjezz
- Complete networking stack rewrite (
Network,TCP,Unix) - #585 by @azjezz Psl\Shellinternals refactored; dead code removed - #596 by @azjezzPsl\Env\temp_dir()now always returns a canonicalized path - #599 by @azjezz
- feat: introduce
Ansicomponent - #588 by @azjezz - feat: introduce
Terminalcomponent - #589 by @azjezz - feat: introduce
Processcomponent - #578 by @azjezz - feat: introduce
Binarycomponent - #598 by @azjezz - feat: introduce
Interoperabilitycomponent - #582 by @azjezz - feat: introduce
TLScomponent - #585 by @azjezz - feat: introduce
UDPcomponent - #585 by @azjezz - feat: introduce
CIDRcomponent - #585 by @azjezz - feat: introduce
Sockscomponent - #585 by @azjezz - feat(network): connection pooling, retry logic, socket pairs - #585 by @azjezz
- feat(datetime): add
Period,Interval,TemporalAmountInterface- #595 by @azjezz - feat(io): add
IO\copy()andIO\copy_bidirectional()- #585 by @azjezz - feat(vec): add
Vec\flatten()- #583 by @azjezz - feat: introduce
Cryptocomponent with symmetric/asymmetric encryption, signing, AEAD, KDF, HKDF, key exchange, and stream ciphers - #607 by @azjezz
- fix(vec): strict comparison in
range()for float precision - #581 by @azjezz - fix(filesystem): canonicalize temporary directory for
create_temporary_file- #580, #597 by @azjezz
- docs: documentation website at https://php-standard-library.dev/ - #592, #594 by @azjezz
- perf: performed optimizations across multiple components, which benchmarks showing up to 100% improvements in certain cases/functions.
- fix(shell): terminate the process on timeout - #574 by @azjezz
- fix(io): correct PHPDoc return type annotation - #571 by @mitelg
- refactor(phpunit): resolve test case naming deprecations - #573 by @simPod
- fix(tree): explicit type precedence - #566 by @azjezz
- fix(iter): do not narrow down
seek($offset)type - #552 by @azjezz - fix(filesystem): release handles before changing permissions when copying files - #550 by @dragosprotung
- revert(option): revert #475 - #560 by @devnix
- chore: add support for PHP 8.5 - #549 by @veewee
- feat: add
Graphcomponent with directed and undirected graph support - #547 by @azjezz - feat: add
Treecomponent for hierarchical data structures - #546 by @azjezz - feat(type): add reflection-based type functions for class members - #543 by @azjezz
- chore: migrate from
maketojust- #544 by @azjezz
- refactor: remove redundant
@vartags from constants - #533 by @azjezz
Psl\Result\wrap()no longer unwraps nested results - #531 by @azjezzPsl\Collection\Map,Psl\Collection\MutableMap,Psl\Collection\Set, andPsl\Collection\MutableSetnow have a more natural JSON serialization - #512 by @josh-rai- A large number of intersection interfaces in the
Psl\IOandPsl\Filenamespaces have been removed to simplify the component's hierarchy - #518 by @azjezz Psl\sequence()function has been removed - #519 by @azjezz
- feat(type): add
containertype - #513 by @azjezz - feat(type): add
int_rangetype - #510 by @george-steel - feat(type): add
always_asserttype - #522 by @azjezz - feat(iter): add
search_with_keys_optandsearch_with_keysfunctions - #490 by @simon-podlipsky
- refactor: improve type inference for non-empty lists - #529 by @azjezz
- refactor: improve type inference for
IterandRegex- #528 by @azjezz
- chore: migrate from
psalmtomago- #527 by @azjezz - chore: replace psalm-specific tags by generic tags - #531 by @azjezz
- feat(encoding): introduce
Base64\Variantenum to support encoding/decoding different variants - #408 by @Gashmob
- fix(option): return
Option<never>forOption::none()- #415 by @devnix - fix(str): add invariant to avoid unexpected errors when parsing an invalid UTF8 string - #410 by @devnix
- feat(type): introduce
Type\convertedfunction - #405 by @veewee - feat(type): introduce
Type\numeric_stringfunction - #406 by @veewee
- feat(result): introduce
Result\try_catchfunction - #403 by @azjezz
- fix(file): improve consistency when creating files for write-mode - #401 by @veewee
- fix(type): un-deprecate
Psl\Type\positive_intfunction - #400 by @dragosprotung
- feat(range): introduced
Psl\Rangecomponent - #378 by @azjezz - feat(str): introduced
Psl\Str\range,Psl\Str\Byte\range, andPsl\Str\Grapheme\rangefunctions - #385 by @azjezz - feat(type): introduced
Psl\Type\uintfunction - #393 by @azjezz - feat(type): introduced
Psl\Type\i8,Psl\Type\i16,Psl\Type\i32,Psl\Type\i64functions - #392 by @azjezz - feat(type): introduced
Psl\Type\u8,Psl\Type\u16,Psl\Type\u32functions - #395 by @KennedyTedesco - feat(type): introduced
Psl\Type\f32, andPsl\Type\f64functions - #396 by @KennedyTedesco - feat(type): introduced
Psl\Type\nonnullfunction - #392 by @azjezz - feat(option): improve options type declarations and add
andThenmethod - #398 by @veewee
- fix(vec/dict): Return might be non-empty-list/non-empty-array for map functions - #384 by @dragosprotung
- chore(async): add async component documentation - #386 by @azjezz
- deprecated
Psl\Type\positive_intfunction, usePsl\Type\uintinstead - by @azjezz
- fix(vec):
Vec\reproduceandVec\rangereturn type is always non-empty-list - #383 by @dragosprotung
- chore: update license copyright year - #371 by @azjezz
- chore: support psalm v5 - #369 by @veewee
- feat(option): introduce option component - #356 by @azjezz
- introduced a new
Psl\Type\unit_enumfunction - @19d1230 by @azjezz - introduced a new
Psl\Type\backed_enumfunction - @19d1230 by @azjezz - introduced a new
Psl\Type\mixed_vecfunction - #362 by @BackEndTea - introduced a new
Psl\Type\mixed_dictfunction - #362 by @BackEndTea
- improved
Psl\Type\vecperformance - #364 by @BackEndTea - improved
Psl\Type\float, andPsl\Type\num- #367 by @bcremer
- updated
revolt-php/event-loopto1.0.0- @c7bf866 by @azjezz - introduced scope-able loader - #361 by @veewee
- fixed wrong function names in examples - #354 by @jrmajor
- added reference to PHPStan integration in README.md - #353 by @ondrejmirtes
-
BC - removed
Psl\Arrcomponent. -
BC - removed
Psl\Type\is_array,Psl\Type\is_arraykey,Psl\Type\is_bool,Psl\Type\is_callable,Psl\Type\is_float,Psl\Type\is_instanceof,Psl\Type\is_int,Psl\Type\is_iterable,Psl\Type\is_null,Psl\Type\is_numeric,Psl\Type\is_object,Psl\Type\is_resource,Psl\Type\is_scalar, andPsl\Type\is_stringfunctions ( useTypeInterface::matches($value)instead ). -
BC - removed
Psl\Iter\chain,Psl\Iter\chunk,Psl\Iter\chunk_with_keys,Psl\Iter\diff_by_key,Psl\Iter\drop,Psl\Iter\drop_while,Psl\Iter\enumerate,Psl\Iter\filter,Psl\Iter\filter_keys,Psl\Iter\filter_nulls,Psl\Iter\filter_with_key,Psl\Iter\flat_map,Psl\Iter\flatten,Psl\Iter\flip,Psl\Iter\from_entries,Psl\Iter\from_keys,Psl\Iter\keys,Psl\Iter\map,Psl\Iter\map_keys,Psl\Iter\map_with_key,Psl\Iter\merge,Psl\Iter\product,Psl\Iter\pull,Psl\Iter\pull_with_key,Psl\Iter\range,Psl\Iter\reductions,Psl\Iter\reindex,Psl\Iter\repeat,Psl\Iter\reproduce,Psl\Iter\reverse,Psl\Iter\slice,Psl\Iter\take,Psl\Iter\take_while,Psl\Iter\to_array,Psl\Iter\to_array_with_keys,Psl\Iter\values, andPsl\Iter\zipfunctions. -
BC - signature of
Psl\Iter\reduce_keysfunction changed fromreduce_keys<Tk, Tv, Ts>(iterable<Tk, Tv> $iterable, (callable(?Ts, Tk): Ts) $function, Ts|null $initial = null): Ts|nulltoreduce_keys<Tk, Tv, Ts>(iterable<Tk, Tv> $iterable, (callable(Ts, Tk): Ts) $function, Ts $initial): Ts. -
BC - signature of
Psl\Iter\reduce_with_keysfunction changed fromreduce_with_keys<Tk, Tv, Ts>(iterable<Tk, Tv> $iterable, (callable(?Ts, Tk, Tv): Ts) $function, Ts|null $initial = null): Ts|nulltoreduce_with_keys<Tk, Tv, Ts>(iterable<Tk, Tv> $iterable, (callable(Ts, Tk, Tv): Ts) $function, Ts $initial): Ts. -
BC - removed bundled psalm plugin
Psl\Integration\Psalm\Plugin, usephp-standard-library/psalm-pluginpackage instead. -
dropped support for PHP 8.0
-
BC - signature of
Psl\Type\objectfunction changed fromobject<T of object>(classname<T> $classname): TypeInterface<T>toobject(): TypeInterface<object>( to preserve the old behavior, usePsl\Type\instance_of) -
introduced
Psl\Type\instance_offunction, with the signature ofinstance_of<T of object>(classname<T> $classname): TypeInterface<T>. -
introduced a new
Psl\Asynccomponent. -
refactored
Psl\IOhandles API. -
introduced a new
Psl\Filecomponent. -
refactor
Psl\Shell\executeto usePsl\IOcomponent. -
introduced a
Psl\IO\pipe(): (Psl\IO\CloseReadHandleInterface, Psl\IO\CloseWriteHandleInterface)function to create a pair of handles, where writes to the WriteHandle can be read from the ReadHandle. -
BC -
$encodingargument forPsl\Strfunctions now acceptsPsl\Str\Encodinginstead of?string. -
introduced a new
Psl\Runtimecomponent. -
introduced a new
Psl\Networkcomponent. -
introduced a new
Psl\TCPcomponent. -
introduced a new
Psl\Unixcomponent. -
introduced a new
Psl\Channelcomponent. -
introduced a new
IO\write()function. -
introduced a new
IO\write_line()function. -
introduced a new
IO\write_error()function. -
introduced a new
IO\write_error_line()functions. -
introduced a new
Psl\Html\Encodingenum. -
BC -
$encodingargument forPsl\Htmlfunctions now acceptsPsl\Html\Encodinginstead of?string. -
BC -
Psl\Shell\escape_commandfunction has been removed, no replacement is available. -
introduced a new
Psl\Math\acosfunction. -
introduced a new
Psl\Math\asinfunction. -
introduced a new
Psl\Math\atanfunction. -
introduced a new
Psl\Math\atan2function. -
BC - The type of the $numbers argument of
Psl\Math\meanhas changed tolist<int|float>instead ofiterable<int|float>. -
BC - The type of the $numbers argument of
Psl\Math\medianhas changed tolist<int|float>instead ofiterable<int|float>. -
introduced a new
Psl\Promisecomponent. -
BC -
Psl\Result\ResultInterfacenow implementsPsl\Promise\PromiseInterface -
BC -
Psl\Type\resource('curl')->toString()now uses PHP built-in resource kind notation ( i.e:resource (curl)) instead of generic notation ( i.e:resource<curl>) -
BC -
Psl\Str,Psl\Str\Byte, andPsl\Str\Graphemefunctions now throwPsl\Str\Exception\OutOfBoundsExceptioninstead ofPsl\Exception\InvaraintViolationsExceptionwhen$offsetis out-of-bounds. -
BC -
Psl\Collection\IndexAccessInterface::at()now throwPsl\Collection\Exception\OutOfBoundsExceptioninstead ofPsl\Exception\InvariantViolationExceptionif$kis out-of-bounds. -
BC -
Psl\Collection\AccessibleCollectionInterface::slicesignature has changed fromslice(int $start, int $length): statictoslice(int $start, ?int $length = null): static -
BC - All psl functions previously accepting
callable, now accept onlyClosure. -
BC -
Psl\DataStructure\QueueInterface::dequeue, andPsl\DataStructure\StackInterface::popnow throwPsl\DataStructure\Exception\UnderflowExceptioninstead ofPsl\Exception\InvariantViolationExceptionwhen the data structure is empty. -
BC -
Psl\Filesystem\write_file($file, $content)function has been removed, usePsl\File\write($file, $content);instead.To preserve the same behavior as the old function, use
Psl\File\write($file, $content, Filesystem\is_file($file) ? File\WriteMode::TRUNCATE : File\WriteMode::OPEN_OR_CREATE). -
BC -
Psl\Filesystem\read_file($file, $offset, $length)function has been removed, usePsl\File\read($file, $offset, $length)instead. -
BC -
Psl\Filesystem\append_file($file, $contents)function has been removed, usePsl\File\write($file, $contents, File\WriteMode::APPEND)instead. -
BC -
Psl\Filesystemfunctions no longer throwPsl\Exception\InvariantViolationException.New exceptions:
Psl\Filesystem\Exception\NotReadableExceptionthrown when attempting to read from a non-readable nodePsl\Filesystem\Exception\NotFileExceptionthrown when attempting a file operation on a non-file node.Psl\Filesystem\Exception\NotDirectoryExceptionthrown when attempting a directory operation on a non-directory node.Psl\Filesystem\Exception\NotSymbolicLinkExceptionthrown when attempting a symbolic link operation on a non-symbolic link node.Psl\Filesystem\Exception\NotFoundExceptionthrown when attempting an operation on a non-existing node.
-
introduced
Psl\Hash\Algorithmenum. -
introduced
Psl\Hash\Hmac\Algorithmenum. -
BC -
Psl\Hash\hash, andPsl\Hash\Context::forAlgorithmnow takePsl\Hash\Algorithmas an algorithm, rather than a string. -
BC -
Psl\Hash\Hmac\hash, andPsl\Hash\Context::hmacnow takePsl\Hash\Hmac\Algorithmas an algorithm, rather than a string. -
BC - A new method
chunk(positive-int $size): CollectionInterfacehas been added toPsl\Collection\CollectionInterface. -
introduced a new
Psl\OScomponent. -
introduced
Psl\Password\Algorithmenum -
BC - all constants of
Psl\Passwordcomponent has been removed. -
BC - function
Psl\Password\algorithms()have been removed. -
BC -
Psl\Result\ResultInterface::getException()method has been renamed toPsl\Result\ResultInterface::getThrowable() -
BC -
Psl\Result\wrapfunction now catches allThrowables instead of onlyExceptions -
introduced a new
Psl\Result\reflectfunction -
BC -
Psl\Shell\escape_argumentfunction has been removed,Shell\executearguments are now always escaped. -
BC -
$escape_argumentsargument ofShell\executefunction has been removed. -
introduced a new
Psl\Shell\ErrorOutputBehaviorenum -
added a new
$error_output_behaviorargument toShell\executefunction, which can be used to return the command error output content, as well as the standard output content. -
introduced a new
Psl\Shell\unpackfunction to unpack packed result ofShell\execute( seePsl\Shell\ErrorOutputBehavior::Packed). -
introduced a new
Psl\Shell\stream_unpackfunction to unpack packed result ofShell\executechunk by chunk, maintaing order ( seePsl\Shell\ErrorOutputBehavior::Packed).