Releases: phalcon/cphalcon
Releases · phalcon/cphalcon
v5.14.1
5.14.1 (2026-06-08)
Tools
- Zephir Parser v2.0.4
- Zephir 0.23.0 (development - bae82f7bd)
Changed
- Consolidated the
Phalcon\Authdual-container handling (newPhalcon\Container\Containervs legacyPhalcon\Di\Di) behind a single internalPhalcon\Auth\Internal\ContainerResolver. #17088 [doc] - Renamed the private
Phalcon\Events\Managerdispatch hot-loop helper torunQueue(). #17006 [doc] - Reworked the
Phalcon\Authaccess gates into Specification-style policies.Phalcon\Contracts\Auth\Access\Access::isAllowed()now receives the current identity and the request context:isAllowed(Guard $guard, string $actionName, array $context = []), where context carrieshandler(controller / task / Micro component name),module(MVC module, when present), andparams(dispatcher or route parameters). #17088 [doc] Phalcon\Auth\Manager::access()now resolves gates throughPhalcon\Auth\Access\AccessLocatorfrom the container instead of constructing them directly. #17088 [doc]
Added
- Added
Phalcon\Auth\Access\Acl- an ACL-backed access gate that incorporates the role-based authorization of the old Firewall component (#14630) into the Auth layer. The gate checks the authenticated user's role against aPhalcon\Acl\Adapter\AdapterInterface: the ACL component is thehandlercontext key (prefixed withmoduleand a configurable separator when present), the ACL access is the action name, andparamsare passed through to callable ACL rules. Unauthenticated requests resolve to a configurable guest role (defaultguest); authenticated users supply their role viaPhalcon\Acl\RoleAwareInterface. #17088 [doc] - Added
Phalcon\Auth\Micro\AuthMicroListenerto enforce the active Auth access gate onPhalcon\Mvc\Microroute execution (attach to themicroevent space).#17088 [doc] - Added
Phalcon\Events\Manager::dispatch(object $event, string|array|null $name = null, ?object $source = null)for object/class-based event dispatch built on Phalcon's ownPhalcon\Contracts\Events\Stoppable. Listeners are routed by an explicit name (a string, or a[class, method]array) or by the event's class name and receive the event object. #17006 [doc] - Added
beforeBindandafterBindhook methods toPhalcon\Forms\Form. When defined on a form subclass,beforeBind(array $data, ?object $entity)runs at the start ofbind()(returningfalsecancels the bind) andafterBind(?object $entity)runs after the data has been assigned. Both also fire whenbind()is reached throughisValid(). #14598 [doc] - Added a
syncoption to many-to-many (hasManyToMany) relations and a chainablePhalcon\Mvc\Model::setSync()method to synchronize related records on save. When enabled, saving deletes the intermediate rows for records no longer present in the assigned array (add/update/delete), instead of only appending. #17071 [doc] - Added a
trace()method toPhalcon\Logger\Loggertogether with a newTRACElog level (value9, labeltrace). #17047 [doc] - Added a
{% verbatim %}/{% endverbatim %}tag to Volt. Its body is emitted exactly as written, without being parsed by Volt, so{{ ... }},{% ... %},{# ... #}and constructs such as<?xml ... ?>or client-side templates (Handlebars, Mustache, Angular) pass through untouched. #17085 [doc] - Added support for
JOINclauses in PHQLUPDATEstatements (e.g.UPDATE Invoices INNER JOIN Customers ON ... SET ... WHERE Customers.cst_id = :id:). The join is used to filter the records to update; the statement still targets a single model. #16984 [doc]
Fixed
- Fixed PHQL parser cache to use string-keyed lookups (
zend_hash_str_find/zend_hash_str_update) instead of integer keys derived fromzend_inline_hash_func, eliminating hash collisions that caused different PHQL queries to return identical cached ASTs #14791 - Fixed
Phalcon\Annotations\Readerfailing to parse a docblock when an annotation argument is a string literal containing a parenthesis (e.g.@SomeAnnotation(key='value(')). The docblock pre-scan that locates each@Annotation(...)span counted every(/), including those inside quoted values, so an unbalanced parenthesis in a string consumed the rest of the comment and produced a "Scanning error". #16084 - Fixed
Phalcon\Di\Injectable::__get()to no longer cache resolved services as dynamic object properties. Services accessed via magic properties (e.g.$this->request) are now re-resolved through the container on each access, so replacing or updating a service in the container is reflected in controllers, views, and other injectable classes. Properties already declared on the class continue to be populated. #17052 - Fixed
Phalcon\Encryption\Crypt::decrypt()to verify the HMAC tag with the constant-timehash_equals()instead of the identity operator, removing an observable timing discrepancy in the tag comparison (CWE-208, CWE-347) . The tag is now also verified before the decrypted text is unpadded, and truncated tags are rejected by the unequal-length path ofhash_equals(). #17090 [doc] - Fixed
Phalcon\Mvc\Model\Query\Builder::orderBy()when the array syntax is used with complex PHQL expressions. Previously any array item containing a space was split as a simplecolumn directionpair, corrupting expressions such asCASE WHEN inv_status_flag = 1 THEN 0 ELSE 1 END ASC. The builder now only treats a trailingASC/DESCas the direction (autoescaping a simple column) and preserves complex expressions verbatim. #17077 - Fixed
Phalcon\Mvc\Model\Query(PHQL) parsing of identifiers whose name begins with theNOTkeyword. Columns, tables, and aliases such asnotice_idwere truncated toice_id(the leadingnotwas dropped), causing the database to report the column as unknown - most visibly inPhalcon\Mvc\Model\Query\Builderjoin conditions built viacreateBuilder(). The scanner's re2c backtracking marker shared the token-start pointer, so theNOT BETWEENrule advanced it pastnot; escaped identifiers containing internal escapes (e.g.[col\[0\]]) were corrupted by the same root cause. #16831 #17087 - Fixed the compilation failure (
'name_zv' undeclared) inPhalcon\Container\Container::callableGet()andcallableNew(). Both closures captured the typedstring nameparameter directly viause (name). #17078
Removed
- Removed the unfinished
{% raw %}/{% endraw %}Volt tag. It never produced output (compilation threwUnknownVoltStatement) and its body was parsed rather than emitted literally. Use{% verbatim %}instead. #17085
v5.14.0
5.14.0 (2026-06-04)
Tools
- Zephir Parser v2.0.2
- Zephir 0.22.0 (development - 9d2def774)
Changed
- Alignment with v6; docblocks; sorting; return types; minor fixes (image watermark opacity calc, serializer/helpers, readonly-becoming-mutable, ACL local access). #17055
- Changed return types to
-> <static>or-> <self>in various components. The change is a covariant narrowing on implementation methods and does not touch any interface contracts, so userland classes that implement Phalcon interfaces and return the interface type continue to work unchanged. #17035 - Internal performance work across
Autoload,Dispatcher,Annotations,Db,Mvc\Model,Mvc\Model\Query,Tag,Assets,Acl\Adapter\Memory,Http\Request,Encryption\Crypt. Behavior preserved. #17049 - Moved CI tools/scripts in
resources/removed unused ones #17066 - Moved docker in
resources/#17066 - Refactored docker images (more flexible less cruft) #17066
- Reorganization of quality tool config files (in
resources/) #17066 Phalcon\Autoload\Loadergetters (getDirectories,getExtensions,getFiles) return arrays keyed by the value string instead of by a SHA256 hash of it; iteration order and contents are unchanged. #17049 [doc]Phalcon\Mvc\Router::handle()internal optimizations: O(1) hash lookup for literal-URI routes; per-HTTP-method buckets; hot-loop reads; PCRE patterns chunked; per-route metadata cache deduplicated by route id. #17012 [doc]Phalcon\Mvc\Router\Route::getCompiledHostName()now uses cache for hostname/converters. #17012 [doc]
Added
- Added a new dependency-injection container under
Phalcon\Container, with its contracts underPhalcon\Contracts\Container. It adds:Phalcon\Container\Container/Phalcon\Container\ContainerFactory- the container and its factory, configured throughPhalcon\Contracts\Container\Service\Providerproviders (Phalcon\Container\Provider\Web,Phalcon\Container\Provider\Cli).Phalcon\Container\Definition\ServiceDefinition- fluent service definitions with autowiring, factories, extenders, tags, aliases, and configurable service lifetimes (Phalcon\Container\Definition\ServiceLifetime).Phalcon\Container\Resolver\Resolver- reflection-based constructor / method / parameter autowiring, plus thePhalcon\Container\Resolver\Lazy\*family for lazy resolution (Get,GetCall,NewInstance,Call,Env,CsEnv,ArrayValues, etc.).Phalcon\Container\Exceptions\*- granular, per-cause exceptions (ServiceNotFound,CircularAliasFound,FrozenDefinition,CannotResolveParameter,NoProcessorFound, etc.). #16897 [doc]
- Added a new authentication and authorization layer under
Phalcon\Auth, with its contracts underPhalcon\Contracts\Auth. Built on top ofPhalcon\Container, it adds:Phalcon\Auth\Manager/Phalcon\Auth\ManagerFactory- the central manager that wires guards and access gates together, and its factory.Phalcon\Auth\AuthUser- a lightweight user value object returned by array-backed adapters when no application model class is configured.- Guards under
Phalcon\Auth\Guard-SessionandToken(withAbstractGuardandUserRemember), resolved viaPhalcon\Auth\Guard\GuardLocatorand configured throughPhalcon\Auth\Guard\Config\*(AbstractGuardConfig,SessionGuardConfig,TokenGuardConfig). - Adapters under
Phalcon\Auth\Adapter-Memory,Model, andStreamuser providers (withAbstractAdapterandAbstractArrayAdapter), resolved viaPhalcon\Auth\Adapter\AdapterLocatorand configured throughPhalcon\Auth\Adapter\Config\*(AbstractAdapterConfig,MemoryAdapterConfig,ModelAdapterConfig,StreamAdapterConfig). - Access gates under
Phalcon\Auth\Access-AuthandGuest(withAbstractAccess), resolved viaPhalcon\Auth\Access\AccessLocator. - Dispatcher listeners
Phalcon\Auth\Mvc\AuthDispatcherListenerandPhalcon\Auth\Cli\AuthDispatcherListener(withPhalcon\Auth\AbstractAuthDispatcherListener) to guard MVC and CLI dispatch. Phalcon\Auth\Exceptionplus granularPhalcon\Auth\Exceptions\*(AccessDenied,ConfigRequiresNonEmptyValue,DataMustContainIdKey,DoesNotImplement,FileCannotRead,FileDoesNotContainJson,FileDoesNotExist,FileNotValidJson).- Contracts under
Phalcon\Contracts\Auth-Manager,AuthUser,AuthRemember,RememberToken,Access\Access,Adapter\Adapter,Adapter\AdapterConfig,Adapter\RememberAdapter,Guard\Guard,Guard\GuardConfig,Guard\GuardStateful,Guard\BasicAuth. Phalcon\Support\AbstractLocator- the shared service-locator base extended by the guard, adapter, and access locators. #16273 [doc]
- Added granular exception classes across the framework. Every namespace that previously surfaced failures through a single umbrella
Phalcon\<Namespace>\Exception(or its sub-namespace counterpart) now ships per-cause classes under a siblingExceptions/folder. Each new class extends the existing per-namespace parent socatch (Phalcon\<Namespace>\Exception $e)continues to work unchanged. New classes:Phalcon\Acl\ExceptionsAccessRuleNotFoundCircularInheritanceErrorElementNotFoundForbiddenWildcardInvalidAccessListInvalidComponentImplementationInvalidRoleImplementationInvalidRoleTypeMissingFunctionParametersParameterTypeMismatchRoleNotFoundException
Phalcon\Annotations\ExceptionsAnnotationNotFoundAnnotationsDirectoryNotWritableCannotReadAnnotationDataUnknownAnnotationExpression
Phalcon\Application\ExceptionsModuleNotRegistered
Phalcon\Assets\ExceptionsAssetSourceTargetCollisionCannotReadAssetCollectionNotFoundInvalidAssetSourcePathInvalidAssetTargetPathInvalidFilterInvalidTargetPathTargetPathIsDirectory
Phalcon\Autoload\ExceptionsLoaderDirectoriesNotArrayLoaderMethodNotCallable
Phalcon\Cache\ExceptionCacheKeysNotIterableInvalidCacheKey
Phalcon\Cli\Console\ExceptionsConsoleModuleNotRegisteredContainerRequiredInvalidModuleDefinitionPathModuleDefinitionPathNotFound
Phalcon\Cli\Router\ExceptionsBeforeMatchNotCallableInvalidRoutePathsRouterArgumentsInvalidType
Phalcon\Config\ExceptionsCannotLoadConfigFileConfigNotArrayOrObjectGroupedAdapterRequiresArrayInvalidMergeDataMissingConfigOptionMissingFileExtensionMissingYamlExtension
Phalcon\DataMapper\Pdo\ExceptionDriverNotSupportedUnknownDriverMethodUnknownQueryMethod
Phalcon\Db\ExceptionsCannotInsertWithoutDataCannotPrepareStatementCheckExpressionRequiredColumnTypeRejectsAutoIncrementColumnTypeRejectsScaleColumnTypeRequiredConflictTargetColumnRequiredConflictUpdateColumnRequiredForeignKeyColumnsRequiredGeneratedAutoIncrementConflictGeneratedDefaultConflictIncompleteBindTypesInvalidBindParameterInvalidCheckExpressionInvalidGenerationExpressionInvalidGroupByExpressionInvalidIndexColumnsInvalidIndexDirectionsInvalidIndexWhereInvalidListExpressionInvalidOrderByExpressionInvalidSqlExpressionInvalidSqlExpressionTypeInvalidUnaryExpressionInvalidWhereConditionsMatchedParameterNotFoundMaterializedViewsNotSupportedMissingDefinitionKeyMissingForeignKeyChecksMissingSqliteDatabaseMysqlOnConflictNotSupportedNestedTransactionChangeBlockedNoActiveTransactionReferencedColumnCountMismatchReferencedColumnsRequiredReferencedTableRequiredReturningNotSupportedReturningRequiresColumnSavepointsNotSupportedSqliteAlterCheckNotSupportedSqliteAlterColumnNotSupportedSqliteAlterForeignKeyNotSupportedSqliteAlterPrimaryKeyNotSupportedSqliteDropCheckNotSupportedSqliteDropForeignKeyNotSupportedSqliteDropPrimaryKeyNotSupportedTableMustHaveColumnUnrecognizedDataTypeUpdateFieldCountMismatch
Phalcon\Di\ExceptionsAliasAlreadyInUseAliasNameMustBeStringArgumentTypeRequiredCallArgumentsMustBeArray- `CircularAliasRefere...
v5.13.0
5.13.0 (2026-05-18)
Changed
- Changed
Phalcon\Contracts\Support\Collectionto declare the expanded method surface (column,each,filter,first,getType,isEmpty,keys,last,map,reduce,replace,sort,values,where) so the contract matches the implementation #17000 [doc] - Changed
Phalcon\Events\Eventto be declaredfinal. The class is a value object holdingtype,source,data,cancelable, andstopped; no subclasses exist in the cphalcon tree and any future typed-event work would add new sibling classes implementingEventInterfacerather than extendingEvent. Marking itfinallets the C extension fold the per-fire getters (getType,getSource,getData,isCancelable,isStopped,isPropagationStopped) into direct dispatch. BC note: any userlandclass MyEvent extends Eventnow fails #17006 [doc] - Changed
Phalcon\Events\Manager::attach()to classify the handler kind once at attach time so the dispatch loop can route via a single branch instead of runninginstanceof Closure/is_callable/typeofper fire per listener. Four kinds are recognized:0= Closure (direct invocation via Zephir's{handler}(args)syntax, no arg-array allocation),1=[obj, method]array callable (direct dynamic dispatchhandler[0]->{handler[1]}(args), nocall_user_func_arrayoverhead),2= plain object with method named after the event - the classic Phalcon listener pattern (class name is captured at attach time and stored on the tuple to skipget_class()per fire),3= generic callable (string function name, invokable object,[class, staticMethod]) routed throughcall_user_func_array. The subscriber array-form attach paths ([methodName, priority]and[[methodA, priorityA], [methodB, priorityB]]) now route throughinsertHandlerEntrydirectly withkind=1, bypassing the classification cascade since the resulting handler shape is already known.methodExistsCacheaccess in the dispatch loop is tightened to a singleissetfast path #17006 [doc] - Changed
Phalcon\Events\Manager::detach()to drop theeventTypekey entirely when its queue empties (removing the last listener), sohasListeners()andfire()'s short-circuit tell the truth. Previously an emptied queue left the key in place with an empty array value, causingisset($this->events[$eventType])to returntruewith no actual listeners to dispatch to. The matchingDetachTestexpectations are updated to reflect the new contract #17006 [doc] - Changed
Phalcon\Events\Manager::detachAll(null)to reseteventsto[]instead ofnull. The previousnullreset brokeisset($this->events[$key])semantics insideattach()andfire()until the next assignment refilled the property; the empty-array form keeps all access paths consistent #17006 [doc] - Changed
Phalcon\Events\Manager::fire()andPhalcon\Events\Manager::fireAll()to wrap dispatch intry { ... } catch \Throwable, ex { cleanup; throw ex; }. A throwing listener restores stashed responses (if nested) and decrementsfireDepthback to its pre-call value before the exception propagates, so manager state stays clean for the next fire - important for long-lived managers (workers, daemons) where a single dirty teardown would poison every subsequent fire #17006 [doc] - Changed
Phalcon\Events\Manager::fire()to parse theeventTypeonly once per unique string and cache the result ([typePrefix, eventName]) in an internaleventNameCachekeyed by the original string. Repeated fires of the same event name (db:beforeQuery × Nper request, model lifecycle events on hot save paths) collapse to a single hash lookup after warm-up. The cache never needs invalidation because the parse is deterministic for a given input string.fire()also short-circuits before allocating theEventinstance when no listeners match either the type queue or the fully-qualified queue - in production most fires have zero matching listeners (model lifecycle events with no user-attached behavior, DB events without a tracer), so the avoided allocation is significant in hot paths #17006 [doc] - Changed
Phalcon\Events\Manager::fire(),Phalcon\Events\Manager::attach(), andPhalcon\Events\Manager::fireQueue()to be declaredfinal. The class itself stays open so genuine subclasses that only add new methods continue to work, but the dispatch hot path is locked to enable C-level direct dispatch on the three methods that run per-event. The remaining public surface (addSubscriber,removeSubscriber,detach,detachAll,getListeners,getResponses,getSubscribers,hasListeners,isCollecting,isValidHandler,collectResponses,enablePriorities,arePrioritiesEnabled,isStrict,setStrict,fireAll,clearSubscribers) is left non-finalso decorator-style subclasses that wrap these less-hot methods can still override them. BC note: subclasses that overridefire,attach, orfireQueuenow fail #17006 [doc] - Changed
Phalcon\Events\Manager::fireQueue()to be a thin BC-preserving wrapper around a new privatePhalcon\Events\Manager::dispatch()helper. The public signaturefireQueue(array $queue, EventInterface $event)is unchanged; the framework's ownfire()path bypassesfireQueueand callsdispatch()directly with hoisted arguments (eventName,source,data,cancelable,collect) so the second dispatch leg of a two-queuefire()(type queue + fully-qualified queue) does not re-extract identical values from the event. The dispatch path also applies a single-handler fast path: when the queue has exactly one listener (very common in unit tests and lightly-instrumented production), the foreach plus per-iteration cancelable/isStopped check is skipped and dispatch goes straight through the type-branch #17006 [doc] - Changed
Phalcon\Events\Managerdispatch return-value contract to last non-null wins. Previously every listener return overwrote the runningstatus, so a chain of ("value",null) ended withfire()returningnulland silently losing the earlier real value. The new contract only updatesstatuswhen the listener return is non-null - the last meaningful return survives. Thestop()determinism rule overrides last-non-null: when a listener calls$event->stop()(andcancelable=true), that listener's return value is whatfire()returns - even ifnull- because the caller asked for the stopping listener's verdict explicitly. Returningfalsefrom a listener does not short-circuit the queue; callers wanting to stop downstream listeners must call$event->stop(). Consumers likePhalcon\Mvc\Dispatcherthat interpret afalsereturn fromfire()as a cancel signal are unaffected because that check happens in their own dispatch logic, not in the events manager #17006 [doc] - Changed
Phalcon\Events\Managerlistener storage fromSplPriorityQueueto a sorted array of[handler, type, priority]tuples (with an additionalclassNameelement ontype=2tuples). TheSplPriorityQueue::EXTR_BOTHclone-per-fire and O(n)setExtractFlags()rebuild on detach are eliminated; the "empty heap" warnings produced bySplPriorityQueueon never-fired event types disappear as a side effect. Insert order under the same priority is preserved (FIFO). WhenenablePrioritiesis off (the default),insertHandlerEntryshort-circuits to a plain append - the sorted-insert loop only runs when priorities are explicitly enabled. When it does run, the insert usesarray_spliceinstead of a per-element rebuild #17006 [doc] - Changed
Phalcon\Html\Escaperinto a façade over five per-context escapers (Phalcon\Html\Escaper\HtmlEscaper,AttributeEscaper,CssEscaper,JsEscaper,UrlEscaper); each is reachable viagetXxxEscaper()/setXxxEscaper()so individual contexts can be swapped without subclassing the façade. The legacysetEncoding(),setFlags(), andsetDoubleEncode()setters fan out to all sub-escapers so existing code keeps working #16971 [doc] - Changed
Phalcon\Html\Helper\AbstractSeries::__toString()toksort()itsstorebefore rendering so entries are emitted in position order rather than registration order. #16971 [doc] - Changed
Phalcon\Html\Helper\Input\CheckboxandPhalcon\Html\Helper\Input\Radioto extend a new sharedPhalcon\Html\Helper\Input\AbstractChecked;Radiono longer extendsCheckbox. Two paths now renderchecked="checked": the unconditional opt-ins["checked" => "checked"](case-insensitive) and["checked" => true], and a value-match path comparing the suppliedcheckedattribute against the input'svalue(==by default for mixed i...
v5.12.1
5.12.1 (2026-04-30)
Added
- Added
Phalcon\Db\Column::TYPE_UUIDconstant (value29) and added support for PostgreSQL nativeuuidcolumn type inPhalcon\Db\Adapter\Pdo\PostgresqlandPhalcon\Db\Dialect\Postgresql#16840 - Added support for
Phalcon\Mvc\Urlstatic base URI inPhalcon\Assets\Manager; when a DI container is set and aurlservice is available, local asset paths are now resolved viagetStatic()instead of a bare/prefix #16570
Fixed
- Fixed
Phalcon\Mvc\Model\MetaDataInterface::readMetaDataIndex()andPhalcon\Mvc\Model\MetaData::readMetaDataIndex()declaring return type asarray|nullwhen the method can also return astring(e.g. forMODELS_IDENTITY_COLUMN), causing a PHP fatal error on PHP 8+ #16613 - Fixed
Phalcon\Mvc\View\Engine\Volt\Compiler::statementList()returningnullinstead ofstringwhen processing templates that consist entirely of block-mode statements, causing a PHP fatal error on PHP 8+ #16613 - Fixed
Phalcon\Forms\Element\Select::render()multiselect regression introduced in v5.12.0 (#16894) by reverting toPhalcon\Tag\Select::selectField(); the newHtml\Helper\Input\Selectonly supports a single selected value and does not handle array values required for multiselect #16946 - Fixed
Phalcon\Html\Helper\Input\AbstractInput::setValue()ignoring empty string""as a valid value, causingCheckboxandRadioinputs withvalue=""to never renderchecked="checked"even when thecheckedattribute matched #16648 - Fixed
Phalcon\Http\Response\Cookies::get()throwing an opaque fatal error when no DI container has been set; it now throwsPhalcon\Http\Cookie\Exceptionwith a descriptive message before accessing the container #16650 - Fixed
Phalcon\Mvc\Model\MetaData::writeMetaDataIndex()prematurely initializing a child model's metadata with the parent's source table whenskipAttributes()(orskipAttributesOnCreate()/skipAttributesOnUpdate()) is called inside a parent model'sinitialize()and the child callsparent::initialize()before setting its own source, corrupting the child's attribute list and breaking relationship resolution #16544 - Fixed
Phalcon\Storage\Serializer\Json::serialize()rejecting plain objects (e.g.stdClass) that do not implementJsonSerializable;json_encode()handles such objects natively and the guard was unnecessary #16630 - Fixed
Phalcon\Mvc\Model\Managerretaining a model instance inlastInitializedafter initialization andPhalcon\Mvc\Modelnot clearing the reusable-records cache aftersave(), causing memory to grow unboundedly in long-running processes #16566 - Fixed
Phalcon\Paginator\Adapter\QueryBuilder::paginate()returning wrong total item count when the query usesDISTINCTcolumns; the count now usesCOUNT(DISTINCT ...)for a single column and a subquery for multiple columns #16581 - Fixed
Phalcon\Mvc\Model\Query\Builder::autoescape()incorrectly wrapping function expressions (e.g.DATE_PART(...)) in brackets when used ingroupBy(), causing a"Column does not belong to any of the selected models"exception #16599 - Fixed
Phalcon\Mvc\Model- saving a model with multiple fields relations threw"Not implemented"#16029
v5.12.0
5.12.0 (2026-04-29)
Changed
- Changed
Phalcon\Assets\Managerfilter type check fromis_object()totypeofand updated the error message to"The filter is not valid"#16889 - Changed
Phalcon\Cache\AbstractCache::doDeleteMultiple()to delegate to the storage adapter'sdeleteMultiple()instead of looping over individualdelete()calls #16859 - Changed
Phalcon\Di\Exceptionmessage for missing services from"was not found in the dependency injection container"to"is not registered in the container"#16889 - Changed
Phalcon\Di\Service\Buildererror messages for service parameters to use double quotes instead of single quotes #16889 - Changed
Phalcon\Forms\Element\AbstractElement::getLocalTagFactory()to throwPhalcon\Forms\Exceptioninstead of silently creating a newTagFactorywhen neithersetTagFactory()nor a parentFormprovides one #16894 - Changed
Phalcon\Forms\Element\Select::render()to useTagFactory-basedHtml\Helper\Input\Selectinstead of the deprecatedPhalcon\Tag\Select#16894 - Changed
Phalcon\Html\TagFactoryto accept an optionalResponseInterfacein the constructor (useful forpreload) #16892 - Changed
Phalcon\Mvc\ControllerandPhalcon\Mvc\View\Engine\AbstractEngineto be events aware #16890 - Changed
Phalcon\Mvc\View\Engine\Volt\Compiler::setOptionsto return$thisnow #16891 - Changed calls to
globals_getandglobals_setin the code withPhalcon\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\Uuidfactory and versioned adapters (Version1–Version7) with aUuidInterfacecarrying standard RFC 4122 namespace constants; each version is a singleton cached by the factory, invoked viav1()–v7()#16326 - Added
Phalcon\Html\Helper\FriendlyTitle- available viaTagFactoryasfriendlyTitle[#16892(https://github.com//issues/16892) - Added
Phalcon\Html\Helper\Input\Select::fromData()to populate select options from aSelectDataInterfaceprovider, with optgroup support #16894 - Added
Phalcon\Html\Helper\Input\Select\SelectDataInterface,Phalcon\Html\Helper\Input\Select\ArrayData, andPhalcon\Html\Helper\Input\Select\ResultsetDataas data providers for theSelecthelper #16894 - Added
Phalcon\Html\Helper\Preload- available viaTagFactoryaspreload;TagFactorynow accepts an optionalResponseInterfaceas 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()toPhalcon\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()throwingInvalidArgumentExceptionfor keys containing invalid characters #16859 - Added named static factory methods
Phalcon\Forms\Exception::tagFactoryNotFound()andPhalcon\Forms\Exception::usingParameterRequired()#16894
Fixed
- Fixed
Phalcon\Db\Dialect\Postgresql::modifyColumn()to generate correct SQL when changing a boolean column's default value: replacedemptycheck withhasDefault()to avoid treatingfalseas "no default", removed the boolean-only branch that omitted theALTER TABLEprefix, and fixedcastDefault()to return PostgreSQL literalstrue/falseinstead of raw PHP booleans #15829 - Fixed
Phalcon\Db\Result\PdoResult::$rowCountto usenullas the uninitialised sentinel instead offalse, preventing a count of0rows being confused with "not yet counted" #16409 - Fixed
Phalcon\Dispatcher\AbstractDispatcher::dispatch()to refresh the localeventsManagerandhasEventsManagervariables afterinitialize()returns, so that an events manager attached to the dispatcher insideinitialize()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 whendatais empty, preventing unnecessaryDi\Exceptionerrors #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 toPhalcon\Messages\Messageinstead of the raw array when multiple fields are provided #16889 - Fixed
Phalcon\Filter\Validation\Validator\Alpha::validate()to returnfalsewhenallowEmptyis explicitly set tofalseand the submitted value isnullor 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()andPhalcon\Html\Escaper::js()to return an empty string instead offalsewhen 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 ofasync="1"when the attribute value istrue#16304 - Fixed
Phalcon\Html\Helper\Breadcrumbsto support subdirectory installs: addedgetPrefix()/setPrefix()for a manual string prefix, and an optionalUrlInterfaceconstructor parameter that resolves links throughurl->get()(including base URI prepending and double-slash normalisation);TagFactoryaccepts an optional fourthUrlInterfaceargument and passes it toBreadcrumbsautomatically #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 handleoffsetX = 0andoffsetY = 0by changing the parameter types frominttovar; the previousinttyping caused Zephir to compile thenullcheck as0 == offsetin C, making explicit zero offsets indistinguishable from omitted (center) offsets #16156 - Fixed
Phalcon\Image\Adapter\Gd::processResize()to preserve PNG alpha channel transparency by replacingimagescale()withimagecreatetruecolor()+imagealphablending(false)+imagesavealpha(true)+imagecopyresampled()#16316 - Fixed
Phalcon\Image\Adapter\Imagick::processPixelate()to explicitly cast division result tointto 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()andPhalcon\Mvc\Model::unserialize()to callonConstruct()after deserialization, so typed properties initialized inonConstructare correctly set when a model is restored from cache #15906 - Fixed
Phalcon\Mvc\Model::__unserialize()andPhalcon\Mvc\Model::unserialize()to restore snapshot as the current attributes (instead of null) when a model is deserialized with no pending changes, preventinggetChangedFields()from throwing after cache retrieval #15837 - Fixed
Phalcon\Mvc\Model::cloneResultMap()to call model setter methods (e.g.setName()) during ORM hydration whenorm.disable_assign_settersisfalse, making hydration behaviour consistent withassign(); setters inlocalMethods(Phalcon internals) are excluded #14810 - Fixed
Phalcon\Mvc\Model::collectRelatedToSave()to skip unmodifiedhasOne/hasManyrelated records that have snapshot data, preventing spuriousINSERT/UPDATEstatem...
v5.11.1
5.11.1 (2026-04-04)
Changed
Added
- Added
Phalcon\Storage\Adapter\RedisClusteradapter to support Redis Cluster connections #16867 - Added
Phalcon\Support\Settingsto be used for ini settings throughout the framework #16873
Fixed
- Fixed
Phalcon\Encryption\Security::computeHmac()to catch\ValueErrorthrown by PHP 8.1+ when an unknown hashing algorithm is passed #16893
Removed
v5.11.0
5.12.0 (2026-04-03)
Changed
- Changed
Phalcon\Filter\Sanitize\IPto optimize the sanatization of IP address #16838 - Changed
Phalcon\Encryption\Security\JWT\Builder::setPassphrase()to require digits and special characters #16847 - Changed
Phalcon\Encryption\Security\JWT\Builder::getAudience()to return an empty array if not set #16846 - Changed
Phalcon\Encryption\Security\Random::base()to use 16 bits by default #16845 - Changed
Phalcon\Logger\Loggerto use lowercase when reporting log levels (previously uppercase) #16852 - Changed
Phalcon\Logger\Adapter\Streamto use a more efficient way to write messages in the logger instead of opening and closing the stream per message #16852 - Changed
Phalcon\Logger\Adapter\Syslogto use theEnuminstead ofLoggerconstants #16852 - Changed the whole testing suite to run on phpunit only #16860 #16861 #16862
Added
- Added PIE (PHP Installer for Extensions) support #16832
- Added the ability to specify aliases for
Phalcon\Di\Diservices.#13042 - Added
Phalcon\Encryption\Security\JWT\Validator::validateClaim()to validate custom claims #16843
Fixed
- Fixed
Phalcon\Forms\Form::isValid()to apply field filters even when no validators are specified #16936 - Fixed
Phalcon\Http\RequestmethodgetClientAddress()when usingtrustForwardedHeader#16836 - Fixed
Phalcon\Acl\Adapter\Memory::isAllowed()andPhalcon\Mvc\Model\Binderto handle PHP 8.1+ union and intersection types by checking forReflectionNamedTypebefore callinggetName()#16261 - Fixed memory leak in PHQL parser (phql_internal_parse_phql()) during repeated query execution. #16854
- Fixed a deadlock issue when running the db suite #16862
Removed
v5.10.0
5.10.0 (2025-12-25)
Changed
- Changed
bind()andvalidate()method inPhalcon\Filter\ValidationandPhalcon\Filter\Validation\ValidationInterfaceto accept$whitelistarray of only allowed fields to be mutated when using entity #16800 - Changed
Phalcon\Storage\Adapters\Libmemcached::getAdapter()to use 50ms for\Memcached::OPT_CONNECT_TIMEOUT#16818 - Changed
Phalcon\Html\Helper\Input\*to honorDocblocdirectives #16778
Added
- Added
fails()method helper toPhalcon\Filter\Validationuseful for standalone validation #16798
Fixed
- Fixed
Phalcon\Config\Adapter\Yamlconstructor to handlenullreturn values fromyaml_parse_file(), ensuring empty configuration files are treated as empty arrays instead of throwing errors. - Fixed
Phalcon\Http\RequestmethodgetClientAddress(true)to return correct IP address from trusted forwarded proxy. #16777 - Fixed
Phalcon\Http\RequestmethodgetPost()to correctly return json data as well and unified bothgetPut()andgetPatch()to go through the same parsing method. #16792 - Fixed
Phalcon\Filter\Validationmethodbind()andvalidate()to correctly bind data when using entity as well as skip binding of fields not included in$whitelist#16800 - Fixed
Phalcon\Http\RequestmethodgetPostData()whenContent-Typeheader is not set #16804 - Fixed
Phalcon\Events\ManagerInterfaceadding priority property #16817 - Fixed
Phalcon\Storage\Adapters\Libmemcached::getAdapter()to correctly merge adapter options #16818 - Fixed
Phalcon\Encryption\CryptmethodcheckCipherHashIsAvailable(string $cipher, string $type)to correctly check thecipherorhashtype #16822 - Fixed
Phalcon\Mvc\Modeldocblocks #16825
v5.9.3
5.9.3 (2025-04-19)
Changed
- Added Multi-Stage Dockerfile and Github action for release Docker images to ghcr.io and Docker Hub. #16752
Added
- Added
Phalcon\Mvc\Router::setUriSource()to allow URI processing from$_GET['url']or$_SERVER['REQUEST_URI']as it was in v3 #16741
Fixed
- Fixed
Phalcon\Mvc\Routerto correctly handle numeric URI parts as it was in v3 #16741 - Fixed
Phalcon\Mvc\Model\Binderto use ReflectionParameter::getType() instead of deprecated method, PHP 8.0 or higher issue. #16742 - Fixed
Phalcon\Mvc\Model\Queryto check if cache entry exists. #16747 - Fixed
Phalcon\Mvc\Routerto correctly match route when using query string URIs. #16749 - Fixed
Phalcon\Mvc\Model::cloneResultsetto properly parse fields that do not acceptnullvalues #16736