github phalcon/cphalcon 5.12.0

6 hours ago

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 (Version1Version7) 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
  • Fixed the CI run to now run Sqlite tests #16920

Removed

Don't miss a new cphalcon release

NewReleases is sending notifications on new releases.