Skip to content

v5.15.0

Latest

Choose a tag to compare

@niden niden released this 18 Jun 15:53
531127b

5.15.0 (2026-06-18)

Tools

  • Zephir Parser v2.0.4
  • Zephir 0.23.0 (development - 27535f802)

Changed

  • Changed Phalcon\Acl\Adapter\Memory to fire the acl:beforeCheckAccess and acl:afterCheckAccess events with an immutable array payload (role, component, access, plus granted on the after event) as the event data, instead of passing the adapter instance. #17143 [doc]
  • Changed Phalcon\Assets\AssetInterface and Phalcon\Assets\FilterInterface to extend the new Phalcon\Contracts\Assets\Asset and Phalcon\Contracts\Assets\Filter contracts. #17147 [doc]
  • Changed Phalcon\Assets\Collection::has() to an O(1) keyed lookup (isset) over the asset store instead of a linear scan. #17147 [doc]
  • Changed Phalcon\Assets\Manager to reject any collection filter that is not a Phalcon\Assets\FilterInterface instance with Phalcon\Assets\Exceptions\InvalidFilter, instead of a fatal error when a non-conforming object reached filter(). #17147 [doc]
  • Changed Phalcon\Auth\Guard\Session to accept an optional Phalcon\Time\Clock\ClockInterface; the remember-me cookie expiry now reads "now" through the clock, defaulting to Phalcon\Time\Clock\SystemClock::fromUTC(). #17151 [doc] [doc]
  • Changed Phalcon\Auth\Manager::attempt() and Phalcon\Auth\Manager::logout() to throw Phalcon\Auth\Exceptions\DoesNotImplement (a subclass of Phalcon\Auth\Exception) when the default guard does not implement GuardStateful. #17148 [doc]
  • Changed Phalcon\Auth\ManagerFactory to validate the required guard configuration keys (type, adapter, and the adapter name) up front, throwing a diagnostic Phalcon\Auth\Exception instead of a notice and TypeError. #17148 [doc]
  • Changed Phalcon\Autoload\Exceptions\LoaderDirectoriesNotArray to accept an optional namespace name; when supplied, the message names the namespace whose directory registration failed. #17149 [doc]
  • Changed Phalcon\Autoload\Loader::getFoundPath() to return the resolved path for every lookup strategy (class map, namespace, directory), not only for file loading. #17149 [doc]
  • Changed Phalcon\Autoload\Loader to drop the redundant directory and namespace-prefix re-normalization on the namespace resolution path (no behavior change). #17149 [doc]
  • Changed Phalcon\Cache\AbstractCache::checkKey() and Phalcon\Cache\AbstractCache::checkKeys() to throw the exception class returned by getExceptionClass() (defaulting to Phalcon\Cache\Exception\InvalidArgumentException) instead of the dedicated InvalidCacheKey / CacheKeysNotIterable subclasses, so the thrown type can be overridden (for example to restore the PSR-16 marker). The exception messages are unchanged. #17156 [doc]
  • Changed Phalcon\Cache\AbstractCache::checkKey() to reject an empty-string key, so every cache operation now throws for "", matching the PSR-16 requirement that keys be non-empty and closing the bare-prefix collision channel. #17164 [doc]
  • Changed Phalcon\Cache\AbstractCache::doDelete() to validate the key before firing the cache:beforeDelete event, matching doGet()/doSet()/doHas(); the event no longer fires for a delete that throws on an invalid key. #17164 [doc]
  • Changed Phalcon\Cache\AbstractCache::doSetMultiple() to validate every key before writing any item, so an invalid key fails the operation up front instead of leaving the already-written pairs persisted behind the thrown exception. #17164 [doc]
  • Changed Phalcon\Cache\CacheInterface to extend the new Phalcon\Contracts\Cache\Cache contract. #17156 [doc]
  • Changed Phalcon\Cli\Router::handle() to return the router instance on every path; the matched branch previously returned null. #17165 [doc]
  • Changed Phalcon\Cli\Router\Exceptions\BeforeMatchNotCallable, Phalcon\Cli\Router\Exceptions\InvalidRoutePaths, and Phalcon\Cli\Router\Exceptions\RouterArgumentsInvalidType to accept optional context (the route pattern, the route pattern, and the received type respectively) and include it in the exception message. #17165 [doc]
  • Changed Phalcon\Cli\Router\Route::beforeMatch() to reject a non-callable callback at registration with Phalcon\Cli\Router\Exceptions\BeforeMatchNotCallable, instead of deferring the failure to match time, matching the Phalcon\Mvc\Router\Route behavior. #17165 [doc]
  • Changed Phalcon\Contracts\Paginator\Adapter::setCurrentPage() and Phalcon\Contracts\Paginator\Adapter::setLimit() to return the Phalcon\Contracts\Paginator\Adapter contract instead of the implementation-side Phalcon\Paginator\Adapter\AdapterInterface, removing the contract layer's dependency on the implementation namespace. Implementations returning the narrower interface remain covariant-compatible. #17153 [doc]
  • Changed Phalcon\Contracts\Paginator\Repository to document the offset and cursor adapter dialects on its getters: cursor adapters (Phalcon\Paginator\Adapter\QueryBuilderCursor) store cursor values in getCurrent()/getNext() and do not compute getTotalItems(), getLast() or getPrevious() (returning 0). #17153 [doc]
  • Changed Phalcon\Db\Adapter\AbstractAdapter::__construct() to reject a dialectClass descriptor object that does not implement Phalcon\Db\DialectInterface with the new Phalcon\Db\Exceptions\InvalidDialectClass at construction time, instead of deferring the failure to first use. #17163 [doc]
  • Changed Phalcon\Db\Adapter\AbstractAdapter::tableExists() and Phalcon\Db\Adapter\AbstractAdapter::tableOptions() to return false and [] respectively when the metadata query returns no rows, instead of emitting a notice on a missing array offset. #17163 [doc]
  • Changed Phalcon\Db\Geometry\GeometryInterface to extend the new Phalcon\Contracts\Db\Geometry\Geometry contract. #17163 [doc]
  • Changed Phalcon\Dispatcher\AbstractDispatcher::callActionMethod() to build the dispatch:beforeCallAction/afterCallAction observer Phalcon\Support\Collection directly instead of resolving it from the DI container by class name, removing a per-action container lookup on the hot path. (Release note: an application that registered a Phalcon\Support\Collection service to override that lookup is no longer consulted here.) #17159 [doc]
  • Changed Phalcon\Dispatcher\AbstractDispatcher::callActionMethod() to re-validate the handler/action pair with is_callable() after the dispatch:beforeCallAction observer runs, so a listener that substitutes a non-existent action now fails through the EXCEPTION_ACTION_NOT_FOUND channel instead of a raw call_user_func_array() fatal. #17159 [doc]
  • Changed Phalcon\Dispatcher\AbstractDispatcher to declare its throwDispatchException() and handleException() error hooks as abstract protected methods and call them directly instead of through dynamic string dispatch. A custom dispatcher that omits either now fails when the class is loaded rather than with an undefined-method fatal on the first error path. #17159 [doc]
  • Changed Phalcon\Dispatcher\AbstractDispatcher to document its three lifecycle hook channels (events-manager listener, duck-typed handler method, and the dispatch:beforeCallAction observer), record the afterBinding blocks' intentional bypass of handleException(), and correct the stale initialize-ordering note that referenced Phalcon 4.0 (no behavior change). #17159 [doc]
  • Changed Phalcon\Dispatcher\DispatcherInterface, Phalcon\Mvc\DispatcherInterface, and Phalcon\Cli\DispatcherInterface to extend the new Phalcon\Contracts\Dispatcher\Dispatcher, Phalcon\Contracts\Mvc\Dispatcher, and Phalcon\Contracts\Cli\Dispatcher contracts. #17159 [doc]
  • Changed Phalcon\Domain\Payload\PayloadInterface, Phalcon\Domain\Payload\ReadableInterface, and Phalcon\Domain\Payload\WriteableInterface to extend the new Phalcon\Contracts\Domain\Payload\Payload, Phalcon\Contracts\Domain\Payload\Readable, and Phalcon\Contracts\Domain\Payload\Writeable contracts. #17162 [doc]
  • Changed Phalcon\Encryption\Crypt::decrypt() to reject input shorter than the selected cipher requires up front with the new Phalcon\Encryption\Crypt\Exception\InvalidDecryptLength, instead of failing later as the less specific Phalcon\Encryption\Crypt\Exception\DecryptionFailed. #17160 [doc]
  • Changed Phalcon\Encryption\Crypt::setAuthTagLength() to validate that the length is between 4 and 16 bytes, throwing the new Phalcon\Encryption\Crypt\Exception\InvalidAuthTagLength instead of accepting any integer. #17160 [doc]
  • Changed Phalcon\Encryption\Crypt\CryptInterface and Phalcon\Encryption\Crypt\Padding\PadInterface to extend the new Phalcon\Contracts\Encryption\Crypt\Crypt and Phalcon\Contracts\Encryption\Crypt\Padding\Pad contracts. #17162 [doc]
  • Changed Phalcon\Encryption\Crypt\PadFactory::padNumberToService() to throw on an unknown padding constant instead of silently mapping it to the no-op padding (fail closed). #17160 [doc]
  • Changed Phalcon\Encryption\Crypt and Phalcon\Encryption\Crypt\CryptInterface to drop the unreachable ECB padding branches (ECB ciphers are filtered out at construction) and to document the encrypted payload wire format (iv ‖ hmac ‖ ciphertext ‖ tag) and the AEAD parameter statefulness. #17160 [doc]
  • Changed Phalcon\Encryption\Security\JWT\Signer\SignerInterface to extend the new Phalcon\Contracts\Encryption\Security\JWT\Signer\Signer contract. #17162 [doc]
  • Changed Phalcon\Encryption\Security\JWT\Validator to accept an optional Phalcon\Time\Clock\ClockInterface constructor parameter for reading the current time; timeShift is retained as the legacy clock-skew mechanism. #17151 [doc] [doc]
  • Changed Phalcon\Encryption\Security\Uuid\UuidInterface, Phalcon\Encryption\Security\Uuid\TimeBasedUuidInterface, and Phalcon\Encryption\Security\Uuid\NodeProviderInterface to extend the new Phalcon\Contracts\Encryption\Security\Uuid\Uuid, Phalcon\Contracts\Encryption\Security\Uuid\TimeBasedUuid, and Phalcon\Contracts\Encryption\Security\Uuid\NodeProvider contracts. #17162 [doc]
  • Changed Phalcon\Flash\AbstractFlash to declare message() as an abstract public method and call it directly from error(), notice(), success(), and warning() instead of through dynamic string dispatch. #17158 [doc]
  • Changed Phalcon\Flash\FlashInterface to extend the new Phalcon\Contracts\Flash\Flash contract. #17158 [doc]
  • Changed Phalcon\Flash\Session::output() to no longer discard the accumulated messages when implicit flush is disabled; it now clears the buffer only in the implicit-flush (echo) mode, so with implicit flush off the rendered messages remain reachable instead of being silently destroyed. #17158 [doc]
  • Changed Phalcon\Html\Attributes::renderAttributes() to escape attribute values through Phalcon\Html\Escaper\AttributeEscaper instead of a hardcoded htmlspecialchars() call, consolidating attribute escaping in one place. Output is byte-identical for the default configuration (ENT_QUOTES, UTF-8, double-encode on). #17157 [doc]
  • Changed Phalcon\Html\Breadcrumbs::render() to return an empty string when no crumbs have been added, instead of indexing end([]) and emitting a PHP warning followed by a malformed single-crumb <dl>. #17157 [doc]
  • Changed Phalcon\Html\Link\Serializer\Header::serialize() to escape embedded backslashes and double quotes in attribute values per the RFC 8288 quoted-string rules, so an attribute value containing a double quote no longer produces a malformed Link header. #17157 [doc]
  • Changed Phalcon\Image\Adapter\AbstractAdapter::background() and Phalcon\Image\Adapter\AbstractAdapter::text() to validate the supplied hex color through a single shared parser, throwing the new Phalcon\Image\Exceptions\InvalidColor for a malformed color instead of silently producing incorrect channel values. #17156 [doc]
  • Changed Phalcon\Image\Adapter\AbstractAdapter to declare its fourteen process* operations as abstract protected methods and call them directly instead of through dynamic string dispatch. A custom adapter that omits one now fails when the class is loaded rather than with an undefined-method fatal on the first operation. #17156 [doc]
  • Changed Phalcon\Image\Adapter\Gd::__construct() to throw Phalcon\Image\Exceptions\ImageLoadFailed when an existing file cannot be read (for example a corrupt or unreadable image), instead of falling through to Phalcon\Image\Exceptions\UnsupportedImageType with no context. #17156 [doc]
  • Changed Phalcon\Logger\AbstractLogger::addMessage() to route each adapter through a direct add()/process() conditional instead of a dynamic method-name dispatch, and normalized the defaultFormatter class-string escaping in Phalcon\Logger\Adapter\AbstractAdapter (no behavior change). #17155 [doc]
  • Changed Phalcon\Logger\AbstractLogger to accept an optional Phalcon\Time\Clock\ClockInterface constructor parameter; log item timestamps now come from the clock, defaulting to a Phalcon\Time\Clock\SystemClock on the logger timezone (current behavior preserved). #17151 [doc] [doc]
  • Changed Phalcon\Logger\Adapter\AbstractAdapter::__destruct() to auto-commit an open transaction, flushing the queued items, instead of throwing Phalcon\Logger\Exceptions\TransactionAlreadyActive. Throwing from a destructor is fatal during script shutdown, so an exception unwinding past a commit() no longer escalates a lost log buffer into a process fatal. #17155 [doc]
  • Changed Phalcon\Logger\Adapter\AbstractAdapter::begin() to throw Phalcon\Logger\Exceptions\TransactionAlreadyActive when a transaction is already active, instead of silently re-arming the flag. #17155 [doc]
  • Changed Phalcon\Logger\LoggerInterface, Phalcon\Logger\Adapter\AdapterInterface, and Phalcon\Logger\Formatter\FormatterInterface to extend the new Phalcon\Contracts\Logger\Logger, Phalcon\Contracts\Logger\Adapter\Adapter, and Phalcon\Contracts\Logger\Formatter\Formatter contracts. #17156 [doc]
  • Changed Phalcon\Messages\Messages::appendMessages() to reject a non-Traversable object with Phalcon\Messages\Exceptions\MessagesNotIterable, instead of a fatal error on rewind(). #17154 [doc]
  • Changed Phalcon\Messages\Messages::offsetSet() to require a Phalcon\Messages\MessageInterface instance, throwing Phalcon\Messages\Exceptions\MessageNotObject for any other value instead of accepting any object; the exception message now states the required type. #17154 [doc]
  • Changed Phalcon\Messages\Messages to implement the new Phalcon\Contracts\Messages\Messages contract; the concrete type is unchanged. #17154 [doc]
  • Changed Phalcon\Mvc\Application\Exceptions\InvalidModuleDefinition and Phalcon\Cli\Console\Exceptions\InvalidModuleDefinition to accept an optional module name and reason in the constructor. The exception message now identifies the offending module and why its definition is invalid. #17146 [doc] [doc]
  • Changed Phalcon\Mvc\ModelInterface::find() to document the four query dialects and their intended lanes (find-parameter arrays, Phalcon\Mvc\Model\Query\Builder, Phalcon\Mvc\Model\Criteria, and raw PHQL) (no behavior change). #17166 [doc]
  • Changed Phalcon\Mvc\Model\MetaData to document its two positional metadata array layouts on the class docblock - the 14-slot attribute array and the 2-slot column map - noting that the two constant families share numeric values and that the metadata cache adapters persist the layout (no behavior change). #17166 [doc]
  • Changed Phalcon\Mvc\Model to document the __get/__call/__callStatic magic-resolution order and finder grammar on its class docblock, and that Phalcon\Mvc\Model::setup() writes process-global orm.* settings that affect every model in the process (no behavior change). #17166 [doc]
  • Changed Phalcon\Paginator\Adapter\AbstractAdapter to require the limit option and Phalcon\Paginator\Adapter\Model to require the model option in their constructors, both throwing Phalcon\Paginator\Exceptions\MissingRequiredParameter, matching the Phalcon\Paginator\Adapter\QueryBuilder and Phalcon\Paginator\Adapter\QueryBuilderCursor adapters. Previously a missing limit reached a division-by-zero in Model/NativeArray and a missing model produced a notice followed by a fatal. #17153 [doc]
  • Changed Phalcon\Paginator\Adapter\QueryBuilderCursor to throw Phalcon\Paginator\Exceptions\InvalidCursorColumn when the cursor column value of the last row is non-numeric, instead of casting it to 0 and silently terminating pagination (e.g. over UUID or ULID keys). #17153 [doc]
  • Changed Phalcon\Paginator\Adapter\QueryBuilder to explicitly initialize its internal hasMultipleGroups flag and documented that the columns constructor option is consumed only by the total-count rewrite for HAVING/GROUP BY queries. #17153 [doc]
  • Changed Phalcon\Session\Adapter\Redis::read() to short-circuit a re-entrant read when this instance already holds the lock for the same session id, returning the held lock instead of spinning against its own lock for the full retry budget before throwing Phalcon\Session\Adapter\Exceptions\AdapterRuntimeError (the session_reset() re-read path). Only the self-deadlock scenario changes. #17167 [doc]
  • Changed Phalcon\Session\Manager::setId() to validate the supplied id against the PHP session-id alphabet ([a-zA-Z0-9,-]), throwing the new Phalcon\Session\Exceptions\InvalidSessionId, matching the cookie validation already performed in start() instead of passing an invalid id straight to session_id(). #17167 [doc]
  • Changed Phalcon\Session\Manager::setName() to reject a digits-only name with Phalcon\Session\Exceptions\InvalidSessionName, instead of letting PHP emit a session_name() warning and silently leave the name unchanged. #17167 [doc]
  • Changed Phalcon\Storage\Adapter\AbstractAdapter::doGet() and the Phalcon\Storage\Adapter\Stream counter and delete internals to route through the protected do* primitives instead of re-entering the public get()/set()/has()/delete() surface. A networked read on Redis/Libmemcached no longer issues a separate EXISTS before GET (roughly halving the round trips), and no fabricated nested before*/after* events are fired - event listeners now observe the real operation sequence (a behavior note for listeners, not a break). #17168 [doc]
  • Changed Phalcon\Storage\Adapter\AbstractAdapter::getArrVal() to delegate to the canonical Phalcon\Support\Helper\Arr\Get helper instead of carrying its own diverged copy (no behavior change). #17168 [doc]
  • Changed Phalcon\Storage\Adapter\AbstractAdapter::getUnserializedData() to guard the isSuccess() call with method_exists(), defaulting to success. A custom serializer implementing only Phalcon\Storage\Serializer\SerializerInterface (which does not declare isSuccess()) no longer fatals on the first cache miss or corrupt entry. #17168 [doc]
  • Changed Phalcon\Storage\Adapter\Redis::getKeys() to enumerate keys with a non-blocking SCAN iteration instead of the blocking KEYS * command, removing the production hazard on large keyspaces while returning the same keys. Phalcon\Storage\Adapter\RedisCluster::getKeys() retains KEYS because cluster SCAN iterates one node at a time. #17168 [doc]
  • Changed Phalcon\Support\Collection::sort() to throw InvalidArgumentException when given a non-callable callback, instead of fataling inside uasort(), and to compare against the SORT_ASC/SORT_DESC constants rather than the literals 4/3. #17152 [doc]
  • Changed Phalcon\Support\Helper\Str\AbstractStr and Phalcon\Support\Helper\Arr\AbstractArr to be marked @internal, documenting that they exist only for their respective helper hierarchies; new code should compose the invokable helpers (Phalcon\Support\Helper\Str\Interpolate, Phalcon\Support\Helper\Arr\Get) rather than extending these bases. #17152 [doc]
  • Changed Phalcon\Support\Settings::get() and Phalcon\Support\Settings::set() to share a single internal reader for the setting whitelist instead of duplicating the list across the read and write paths, removing the drift risk between them. #17152 [doc]
  • Changed Phalcon\Translate\Adapter\AbstractAdapter and Phalcon\Translate\Interpolator\AssociativeArray to memoize the interpolator instance and the Phalcon\Support\Helper\Str\Interpolate helper respectively, removing two object allocations per translation call on the hot path. #17150 [doc]
  • Changed Phalcon\Translate\Adapter\AbstractAdapter to host the triggerError strict-mode option and the notFound() hook (lifted from Phalcon\Translate\Adapter\NativeArray), so Phalcon\Translate\Adapter\Csv and Phalcon\Translate\Adapter\Gettext now also support strict mode - a missing key throws Phalcon\Translate\Exceptions\KeyNotFound when triggerError is enabled. Defaults preserve current behavior. #17150 [doc]
  • Changed several Phalcon\Assets exceptions to provide better descriptions. #17147 [doc]
  • Changed the Redis fast path in Phalcon\Cache\AbstractCache::doGetMultiple() to validate each key, accept Traversable inputs (previously a TypeError on the Redis adapter only), and apply the serializer's full unserialize protocol (returning the default value for a corrupt entry), aligning it with the per-key loop path used by the other adapters. #17164 [doc]
  • Changed the Phalcon\Application\Exceptions\ModuleNotRegistered message to be more descriptive. #17146 [doc] [doc]
  • Changed the Phalcon\Auth\Guard\Session auth:* events to fire as non-cancellable, matching that their return value was already ignored. #17148 [doc]
  • Changed the Phalcon\Auth\Guard\Session remember-me cookie lifetime to a configurable Phalcon\Auth\Guard\Config\SessionGuardConfig value (rememberTtl, default DEFAULT_REMEMBER_TTL); the default is now 365 days (previously a hardcoded 360). #17148 [doc]
  • Changed the Phalcon\Auth adapters (Memory, Stream, Model) to verify the configured user model implements Phalcon\Contracts\Auth\AuthUser during hydration, throwing Phalcon\Auth\Exceptions\DoesNotImplement instead of failing later. #17148 [doc]
  • Changed the Phalcon\Autoload\Loader class-map strategy to fire the loader:beforeCheckPath event before probing, matching the namespace and directory strategies. #17149 [doc]
  • Changed the Phalcon\Flash\Exceptions\EscaperServiceUnavailable and Phalcon\Flash\Exceptions\SessionServiceUnavailable messages to "The '' service is not available (no container, or service not registered)", describing both trigger conditions (no container at all, or a container that lacks the service). #17158 [doc]
  • Deprecated Phalcon\Assets\Filters\Cssmin and Phalcon\Assets\Filters\Jsmin; both return the content unchanged (the minification has never been implemented). #17147 [doc]
  • Deprecated Phalcon\Cli\Router::getParams() and Phalcon\Cli\RouterInterface::getParams() in favor of getParameters(). #17165 [doc]
  • Deprecated the Phalcon\Dispatcher\AbstractDispatcher and Phalcon\Dispatcher\DispatcherInterface parameter accessors getParam(), getParams(), hasParam(), setParam(), and setParams() in favor of their getParameter(), getParameters(), hasParameter(), setParameter(), and setParameters() counterparts; the deprecated spellings will be removed in the next major version. #17159 [doc]
  • Deprecated the Phalcon\Encryption\Security constants CRYPT_STD_DES, CRYPT_EXT_DES, CRYPT_BLOWFISH, and CRYPT_BLOWFISH_Y (never implemented; they resolve to bcrypt) and CRYPT_MD5 (weak legacy algorithm); any unhandled defaultHash value resolves to bcrypt. #17160 [doc]

Added

  • Added Phalcon\Contracts\Assets\Asset and Phalcon\Contracts\Assets\Filter, the canonical contracts for Phalcon\Assets\Asset and the Assets filters. They are the long-term replacements for the deprecated Phalcon\Assets\AssetInterface and Phalcon\Assets\FilterInterface. #17147 [doc]
  • Added Phalcon\Contracts\Cache\Cache, the canonical contract for Phalcon\Cache\Cache (the PSR-16-shaped cache surface). It is the long-term replacement for the deprecated Phalcon\Cache\CacheInterface. #17156 [doc]
  • Added Phalcon\Contracts\Db\Geometry\Geometry, the canonical contract for the Phalcon\Db\Geometry value objects (getSrid(), getType(), toWkt()). It is the long-term replacement for the deprecated Phalcon\Db\Geometry\GeometryInterface. #17163 [doc]
  • Added Phalcon\Contracts\Dispatcher\Dispatcher, Phalcon\Contracts\Mvc\Dispatcher, and Phalcon\Contracts\Cli\Dispatcher, the canonical contracts for Phalcon\Dispatcher\AbstractDispatcher, Phalcon\Mvc\Dispatcher, and Phalcon\Cli\Dispatcher. They are the long-term replacements for the deprecated Phalcon\Dispatcher\DispatcherInterface, Phalcon\Mvc\DispatcherInterface, and Phalcon\Cli\DispatcherInterface. #17159 [doc]
  • Added Phalcon\Contracts\Flash\Flash, the canonical contract for the Phalcon\Flash messengers (Phalcon\Flash\Direct, Phalcon\Flash\Session). It is the long-term replacement for the deprecated Phalcon\Flash\FlashInterface. #17158 [doc]
  • Added Phalcon\Contracts\Logger\Logger, Phalcon\Contracts\Logger\Adapter\Adapter, and Phalcon\Contracts\Logger\Formatter\Formatter, the canonical contracts for Phalcon\Logger\Logger, its adapters, and its formatters. They are the long-term replacements for the deprecated Phalcon\Logger\LoggerInterface, Phalcon\Logger\Adapter\AdapterInterface, and Phalcon\Logger\Formatter\FormatterInterface. #17156 [doc]
  • Added Phalcon\Contracts\Messages\Messages, the canonical contract for the Phalcon\Messages\Messages collection (append, count, filter, and iteration); the collection previously had no interface of its own. #17154 [doc]
  • Added Phalcon\Db\Exceptions\InvalidDialectClass, thrown by Phalcon\Db\Adapter\AbstractAdapter::__construct() when the dialectClass descriptor object does not implement Phalcon\Db\DialectInterface. #17163 [doc]
  • Added Phalcon\Dispatcher\AbstractDispatcher::getPreviousActionName(), Phalcon\Dispatcher\AbstractDispatcher::getPreviousHandlerName(), and Phalcon\Dispatcher\AbstractDispatcher::getPreviousNamespaceName(), lifting the previously MVC-only previous-dispatch getters to the base so Phalcon\Cli\Dispatcher gains them too. Phalcon\Mvc\Dispatcher::getPreviousControllerName() remains as a controller-named alias. #17159 [doc]
  • Added Phalcon\Encryption\Crypt\Exception\InvalidAuthTagLength and Phalcon\Encryption\Crypt\Exception\InvalidDecryptLength. #17160 [doc]
  • Added Phalcon\Image\Adapter\Gd::create() and Phalcon\Image\Adapter\Imagick::create(), static named constructors for the blank-canvas case that avoid the constructor's load-or-create ambiguity. #17156 [doc]
  • Added Phalcon\Image\Exceptions\InvalidColor, thrown when a malformed hex color is passed to Phalcon\Image\Adapter\AbstractAdapter::background() or Phalcon\Image\Adapter\AbstractAdapter::text(). #17156 [doc]
  • Added Phalcon\Logger\AbstractLogger::begin(), Phalcon\Logger\AbstractLogger::commit(), and Phalcon\Logger\AbstractLogger::rollback(), which fan the transaction out across every non-excluded adapter, so transactions can be controlled at the logger level instead of one adapter at a time. #17155 [doc]
  • Added a correctly-spelled "pkcs7" service alias to Phalcon\Encryption\Crypt\PadFactory alongside the existing (misspelled) "pjcs7", so newInstance("pkcs7") resolves the PKCS7 padding. #17160 [doc]
  • Added an optional sessionKey constructor parameter to Phalcon\Flash\Session (defaulting to the existing _flashMessages key), letting multi-instance applications namespace their flash messages instead of sharing one session slot. #17158 [doc]
  • Added the Phalcon\Db\Dialect::supportsReturning(), Phalcon\Db\Dialect::supportsOnConflictUpdate(), Phalcon\Db\Dialect::supportsMaterializedViews(), and Phalcon\Db\Dialect::supportsAlterTable() capability predicates (overridden per dialect to match each backend) so callers can detect an optional feature instead of catching its dedicated exception. #17163 [doc]

Fixed

  • Fixed Phalcon\Autoload\Loader reporting a successful autoload for a class-map entry whose mapped file does not exist; the class-map strategy now honors the require result and falls through to the namespace and directory strategies instead of short-circuiting them. #17149 [doc]
  • Fixed Phalcon\Db\Adapter\Pdo\Mysql::describeColumns() treating a column declared DEFAULT NULL as having the string "NULL" as its default (MySQL's INFORMATION_SCHEMA.COLUMNS.COLUMN_DEFAULT reports it that way since the 5.13.0 switch away from SHOW FULL COLUMNS); the sentinel is now read as no default. This stops a nullable column whose value is null from being turned into the string "NULL" on the model attribute after save(). #17176 [doc]
  • Fixed Phalcon\Encryption\Crypt::decrypt() extracting the GCM/CCM authentication tag with str_replace(), which stripped every occurrence of the tag's byte sequence from the ciphertext rather than only the trailing tag. With short auth tags an interior collision corrupted the ciphertext and made a valid AEAD payload fail authentication; the tag is now split off by length. #17160 [doc]
  • Fixed Phalcon\Encryption\Crypt\Padding\Pkcs7 and Phalcon\Encryption\Crypt\Padding\Zero measuring binary padded data with the encoding-sensitive mb_strlen(); on a multibyte-capable internal encoding this computed the padding size from the wrong byte and silently mis-unpadded. Both now use byte-true strlen(). #17160 [doc]
  • Fixed Phalcon\Encryption\Security::hash() discarding caller-supplied Argon2 tuning options (memory_cost, time_cost, threads); it rebuilt the options array with only cost, so a hardened configuration silently ran with defaults. The caller's options are now preserved. #17160 [doc]
  • Fixed Phalcon\Filter\Validation::bind() emitting an Invalid arguments supplied for camelize() warning when the data being validated against an entity contained a numeric (integer) key, as happened with Phalcon\Forms\Form::isValid($data, $entity); integer keys are now skipped during entity binding. #17173 [doc]
  • Fixed Phalcon\Logger\AbstractLogger::excludeAdapters() leaving the exclusion list armed across calls when the level filter discarded the message; the list is now cleared on every Phalcon\Logger\AbstractLogger::addMessage() call, so an exclusion is consumed by the call that set it instead of skipping adapters on the next, unrelated log call. #17155 [doc]
  • Fixed Phalcon\Mvc\Model::sum() and Phalcon\Mvc\Model::average() returning null on an empty result set, which violated their declared float | ResultsetInterface return type and raised a TypeError in any subclass that overrode them with the same type and delegated through parent. Both now coerce the empty aggregate to 0.0. #17184 [doc]
  • Fixed Phalcon\Mvc\Router\Route::compilePattern() and Phalcon\Cli\Router\Route::compilePattern() expanding the :params placeholder - and the built-in /:controller/:action/:params and /:task/:action/:params default routes - to the nested quantifier (/.*)*. The group body overlaps itself, so an unmatchable trailing byte made the compiled pattern backtrack catastrophically: a short crafted URI (a run of / followed by a byte . cannot match) drove the preg_match() in Phalcon\Mvc\Router::handle() / Phalcon\Cli\Router::handle() into exponential time on every request. The trailing group is now compiled to the equivalent (/.*)?, which captures the same params value in linear time. [doc]
  • Fixed Phalcon\Support\Collection (and every descendant, including Phalcon\Config\Config and Phalcon\Html\Attributes) orphaning the previously stored entry when a key was overwritten with a different letter casing on a case-insensitive collection. set("Key", 1) followed by set("KEY", 2) left both entries in the backing store, so count(), toArray(), and iteration disagreed with get(), has(), and remove(). The stale entry is now evicted before the new value is written. #17152 [doc]
  • Fixed Phalcon\Time\Clock\FrozenClock::adjust() leaving the process-global warning.enable flag clobbered on the pre-PHP-8.3 fallback path; the prior value is now restored on both exits. #17151 [doc]
  • Fixed the Phalcon\Acl\Adapter\Memory documentation and metadata. #17143 [doc]
  • Fixed the Phalcon\Autoload\Loader debug trail (getDebug()) being wiped by nested autoloads (a class requiring a not-yet-loaded parent); the trail is now reset only on the outermost call. #17149 [doc]
  • Fixed the loader:pathFound event in Phalcon\Autoload\Loader firing more than once per load (and, for the class-map strategy, before the file was confirmed); it now fires once, from the point that loads the file. #17149 [doc]

Removed

  • Removed Phalcon\Cache\Exception\InvalidCacheKey and Phalcon\Cache\Exception\CacheKeysNotIterable. Phalcon\Cache\AbstractCache::checkKey() and checkKeys() now throw Phalcon\Cache\Exception\InvalidArgumentException with the same messages. #17156 [doc]