You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
5.12.0 (2026-04-29)
Changed
Changed Phalcon\Assets\Manager filter type check from is_object() to typeof and updated the error message to "The filter is not valid"#16889
Changed Phalcon\Cache\AbstractCache::doDeleteMultiple() to delegate to the storage adapter's deleteMultiple() instead of looping over individual delete() calls #16859
Changed Phalcon\Di\Exception message for missing services from "was not found in the dependency injection container" to "is not registered in the container"#16889
Changed Phalcon\Di\Service\Builder error messages for service parameters to use double quotes instead of single quotes #16889
Changed Phalcon\Forms\Element\AbstractElement::getLocalTagFactory() to throw Phalcon\Forms\Exception instead of silently creating a new TagFactory when neither setTagFactory() nor a parent Form provides one #16894
Changed Phalcon\Forms\Element\Select::render() to use TagFactory-based Html\Helper\Input\Select instead of the deprecated Phalcon\Tag\Select#16894
Changed Phalcon\Html\TagFactory to accept an optional ResponseInterface in the constructor (useful for preload) #16892
Changed Phalcon\Mvc\Controller and Phalcon\Mvc\View\Engine\AbstractEngine to be events aware #16890
Changed Phalcon\Mvc\View\Engine\Volt\Compiler::setOptions to return $this now #16891
Changed calls to globals_get and globals_set in the code with Phalcon\Support\Settings::get()/set()#16884
Changed exception messages across multiple components to use "does not" instead of "doesn't" for consistency #16889
Added
Added Phalcon\Encryption\Security\Uuid factory and versioned adapters (Version1–Version7) with a UuidInterface carrying standard RFC 4122 namespace constants; each version is a singleton cached by the factory, invoked via v1()–v7()#16326
Added Phalcon\Html\Helper\FriendlyTitle - available via TagFactory as friendlyTitle [#16892(https://github.com//issues/16892)
Added Phalcon\Html\Helper\Input\Select::fromData() to populate select options from a SelectDataInterface provider, with optgroup support #16894
Added Phalcon\Html\Helper\Input\Select\SelectDataInterface, Phalcon\Html\Helper\Input\Select\ArrayData, and Phalcon\Html\Helper\Input\Select\ResultsetData as data providers for the Select helper #16894
Added Phalcon\Html\Helper\Preload - available via TagFactory as preload; TagFactory now accepts an optional ResponseInterface as its third constructor parameter [#16892(https://github.com//issues/16892)
Added Phalcon\Mvc\Model\Resultset::refresh() to re-execute the underlying query and update the resultset with fresh data from the database #16409
Added deleteMultiple() to Phalcon\Storage\Adapter\* to delete multiple keys in a single operation using native batch capabilities per adapter #16859
Added key validation per entry in Phalcon\Cache\AbstractCache::doDeleteMultiple() throwing InvalidArgumentException for keys containing invalid characters #16859
Added named static factory methods Phalcon\Forms\Exception::tagFactoryNotFound() and Phalcon\Forms\Exception::usingParameterRequired()#16894
Fixed
Fixed Phalcon\Db\Dialect\Postgresql::modifyColumn() to generate correct SQL when changing a boolean column's default value: replaced empty check with hasDefault() to avoid treating false as "no default", removed the boolean-only branch that omitted the ALTER TABLE prefix, and fixed castDefault() to return PostgreSQL literals true/false instead of raw PHP booleans #15829
Fixed Phalcon\Db\Result\PdoResult::$rowCount to use null as the uninitialised sentinel instead of false, preventing a count of 0 rows being confused with "not yet counted" #16409
Fixed Phalcon\Dispatcher\AbstractDispatcher::dispatch() to refresh the local eventsManager and hasEventsManager variables after initialize() returns, so that an events manager attached to the dispatcher inside initialize() is honoured for all subsequent dispatch events (afterInitialize, afterExecuteRoute, afterDispatch, afterDispatchLoop, etc.) #16440
Fixed Phalcon\Filter\Validation::bind() to skip the dependency injection container lookup when data is empty, preventing unnecessary Di\Exception errors #16889
Fixed Phalcon\Filter\Validation\AbstractValidator::allowEmpty() to support a value-list array (e.g. [null, '']) in addition to the per-field map syntax, using strict === comparison so that '0' is never silently treated as empty #15491
Fixed Phalcon\Filter\Validation\AbstractValidator::messageFactory() to pass the joined field string to Phalcon\Messages\Message instead of the raw array when multiple fields are provided #16889
Fixed Phalcon\Filter\Validation\Validator\Alpha::validate() to return false when allowEmpty is explicitly set to false and the submitted value is null or an empty string #16200
Fixed Phalcon\Forms\Form::isValid() to apply field filters even when no validators are specified (again) #16830
Fixed Phalcon\Html\Escaper::css() and Phalcon\Html\Escaper::js() to return an empty string instead of false when the input is empty or contains only a null codepoint #16889
Fixed Phalcon\Html\Helper\AbstractHelper::renderAttributes() to emit boolean HTML5 attributes (e.g. async, defer) as standalone attribute names instead of async="1" when the attribute value is true#16304
Fixed Phalcon\Html\Helper\Breadcrumbs to support subdirectory installs: added getPrefix()/setPrefix() for a manual string prefix, and an optional UrlInterface constructor parameter that resolves links through url->get() (including base URI prepending and double-slash normalisation); TagFactory accepts an optional fourth UrlInterface argument and passes it to Breadcrumbs automatically #14957
Fixed Phalcon\Http\Response::setStatusCode() exception message from "Non-standard statuscode given without a message" to "Non-standard status-code given without a message"#16889
Fixed Phalcon\Image\Adapter\AbstractAdapter::crop() to correctly handle offsetX = 0 and offsetY = 0 by changing the parameter types from int to var; the previous int typing caused Zephir to compile the null check as 0 == offset in C, making explicit zero offsets indistinguishable from omitted (center) offsets #16156
Fixed Phalcon\Image\Adapter\Gd::processResize() to preserve PNG alpha channel transparency by replacing imagescale() with imagecreatetruecolor() + imagealphablending(false) + imagesavealpha(true) + imagecopyresampled()#16316
Fixed Phalcon\Image\Adapter\Imagick::processPixelate() to explicitly cast division result to int to prevent implicit float-to-int deprecation #16889
Fixed Phalcon\Mvc\Model::__get() to return the already-loaded related record instead of re-fetching from the database, preventing modifications to relation properties from being discarded #15554
Fixed Phalcon\Mvc\Model::__unserialize() and Phalcon\Mvc\Model::unserialize() to call onConstruct() after deserialization, so typed properties initialized in onConstruct are correctly set when a model is restored from cache #15906
Fixed Phalcon\Mvc\Model::__unserialize() and Phalcon\Mvc\Model::unserialize() to restore snapshot as the current attributes (instead of null) when a model is deserialized with no pending changes, preventing getChangedFields() from throwing after cache retrieval #15837
Fixed Phalcon\Mvc\Model::cloneResultMap() to call model setter methods (e.g. setName()) during ORM hydration when orm.disable_assign_setters is false, making hydration behaviour consistent with assign(); setters in localMethods (Phalcon internals) are excluded #14810
Fixed Phalcon\Mvc\Model::collectRelatedToSave() to skip unmodified hasOne/hasMany related records that have snapshot data, preventing spurious INSERT/UPDATE statements when a relation is read but not changed #16000
Fixed Phalcon\Mvc\Model::doLowInsert() to also reset uniqueKey (in addition to uniqueParams) after an auto-increment INSERT so that a subsequent has() call on the same record rebuilds the primary-key condition from current attribute values; previously, uniqueParams was cleared but uniqueKey was kept, causing has() to query with a null parameter and return false, which made SoftDelete attempt to INSERT an already-existing belongsTo related record instead of updating it #16453
Fixed Phalcon\Mvc\Model::doLowUpdate() to skip columns whose string value matches the column's function-call DB default (e.g. gen_random_uuid()) in the non-dynamic update path, preventing the function name from being passed as a bound string parameter and causing a DB type error #15828
Fixed Phalcon\Mvc\Model::doSave() to capture the model snapshot before the INSERT/UPDATE and restore it when postSaveRelatedRecords fails and rolls back the transaction; previously, with orm.update_snapshot_on_save enabled, the snapshot was permanently updated inside doLowInsert/doLowUpdate even when the transaction was rolled back, causing Dynamic Update to silently skip the write on the next save attempt #16410
Fixed Phalcon\Mvc\Model::getRelated() to return already-fetched relations from the internal cache (dirtyRelated first, then related) instead of always querying the database; cache is cleared after save() and delete() to prevent stale results #16409
Fixed Phalcon\Mvc\Model::toArray() to catch Error thrown by a getter that accesses an uninitialized typed PHP property (can occur when cloneResultMap() skips a null value for a NOT NULL column, e.g. via a LEFT JOIN), returning null instead of propagating the error #15711
Fixed Phalcon\Mvc\Model::unserialize() to catch TypeError when assigning a serialised null back to a typed non-nullable PHP property, preventing a crash on the second request when the model is loaded from a cache like APCu #15711
Fixed Phalcon\Mvc\Model\Manager::getRelationRecords() to apply reusable caching for hasManyToMany and hasOneThrough relations; reusable: true was previously ignored for through-relations #15934
Fixed Phalcon\Mvc\Model\Query::executeSelect() to embed Phalcon\Db\RawValue bind parameters directly in the SQL string instead of passing them to PDO #16350
Fixed Phalcon\Mvc\Model\Query::executeSelect() to use the write connection when the query contains a FOR UPDATE clause, instead of always using the read connection #16032
Fixed Phalcon\Mvc\Model\Query::getExpression() to emit NOT BETWEEN instead of BETWEEN NOT for the PHQL_T_BETWEEN_NOT token, producing valid SQL #16812
Fixed Phalcon\Mvc\Model\Query::getSelectColumn() to use the full model class name as the balias key in a complex resultset when the model is namespaced (e.g. App\Models\Users), instead of incorrectly applying lcfirst() to the fully-qualified name; non-namespaced models (e.g. Robots) retain the existing lcfirst() behaviour (robots) #16052
Fixed Phalcon\Mvc\Model\Query\Builder::getPhql() to use a named bind parameter (:APK0:) instead of embedding the raw primary-key value in the PHQL string when findFirst() is called with a numeric or numeric-string argument; this prevents unbounded growth of the internal PHQL AST cache (Query::$internalPhqlCache) in long-running CLI processes #14656
Fixed Phalcon\Mvc\Model\Resultset\Complex::current() to return null instead of an empty model instance when a LEFT JOIN produces no matching row (all column values are null) #16239
Fixed Phalcon\Mvc\Model\Transaction\Manager::collectTransaction() to keep the correct transactions when rebuilding the list after removal #16522
Fixed Phalcon\Mvc\Model\Transaction\Manager::commit() to remove each transaction from the pool after committing so that subsequent get() calls return a fresh transaction #16522
Fixed Phalcon\Mvc\Model to handle the `lastInsertId correctly under Postgres #16920#16436#15775
Fixed Phalcon\Mvc\Router\Annotations::handle() to strip the controllerSuffix from the class name when a fully-qualified class name already includes it (e.g. App\Controllers\InvoicesController), preventing the doubled suffix InvoicesControllerController#16238
Fixed Phalcon\Paginator\Adapter\QueryBuilder::paginate() to correctly count groups when groupBy() receives a multi-column array, using a SELECT DISTINCT subquery instead of the PostgreSQL-incompatible COUNT(DISTINCT col1, col2) form #15912
Fixed Phalcon\Paginator\Adapter\QueryBuilder::paginate() to use the columns option as the COUNT(DISTINCT ...) argument when a GROUP BY is present, allowing NULL-safe expressions to be supplied #15266
Fixed Phalcon\Storage\Adapter\Libmemcached, Phalcon\Storage\Adapter\Redis and Phalcon\Storage\Adapter\Weak to call initSerializer() during construction #16889
Fixed Phalcon\Storage\Adapter\Redis to initialize lifetime from options during construction #16889
Fixed Phalcon\Support\Helper\Json\Encode to prefix the InvalidArgumentException message with "json_encode error: " for consistency #16889
Fixed the CI run to correctly use updated changes, and reuse artifacts #16920
Fixed the CI run to now run Postgresql tests #16920