Skip to content

Latest commit

 

History

History
259 lines (199 loc) · 12.2 KB

File metadata and controls

259 lines (199 loc) · 12.2 KB

Version 4.7.0

Release Date: Unreleased

4.7.0 release of CodeIgniter4

  • Update minimal PHP requirement to 8.2.

Placeholders in the regex_match validation rule must now use double curly braces. If you previously used single braces like regex_match[/^{placeholder}$/], you must update it to use double braces: regex_match[/^{{placeholder}}$/].

This change was introduced to avoid ambiguity with regular expression syntax, where single curly braces (e.g., {1,3}) are used for quantifiers.

The insertBatch() and updateBatch() methods now honor model settings like updateOnlyChanged and allowEmptyInserts. This change ensures consistent handling across all insert/update operations.

Primary Key Validation

The insert() and insertBatch() (when useAutoIncrement is disabled), update(), and delete() methods now validate primary key values before executing database queries. Invalid primary key values will now throw InvalidArgumentException instead of DatabaseException.

What changed:

  • Exception type: Invalid primary keys now throw InvalidArgumentException with specific error messages instead of generic DatabaseException from the database layer.

  • Validation timing:

    • For update() and delete(): Validation happens before the beforeUpdate/beforeDelete events and before any database queries are executed.
    • For insert() and insertBatch() (when auto-increment is disabled): Validation happens after the beforeInsert event but before database queries are executed.
  • Invalid values: The following values are now explicitly rejected as primary keys:

    • null (for insert when auto-increment is disabled)
    • 0 (integer zero)
    • '0' (string zero)
    • '' (empty string)
    • true and false (booleans)
    • [] (empty array)
    • Nested arrays (e.g., [[1, 2]])
    • Arrays containing any of the above invalid values

    Note: RawSql objects are allowed as primary key values for complex scenarios where you need to use raw SQL expressions.

This change improves error reporting by providing specific validation messages (e.g., "Invalid primary key: 0 is not allowed") instead of generic database errors, and prevents invalid queries from reaching the database.

If you need to allow some of these values for the primary key, you can override the validateID() method in your model.

The Entity::hasChanged() and Entity::syncOriginal() methods now perform deep comparison for objects and arrays instead of shallow comparison. This means:

  • Objects and arrays are now JSON-encoded and normalized for comparison, detecting changes in nested structures, object properties, and array elements.
  • Enums (both BackedEnum and UnitEnum) are properly tracked by their backing value or case name.
  • DateTime objects (DateTimeInterface) are compared using their ISO 8601 representation including timezone information.
  • Collections (Traversable) such as ArrayObject and ArrayIterator are converted to arrays for comparison.
  • Value objects with __toString() method are compared by their string representation when properties are not accessible (fallback for objects with private properties).
  • Nested entities (using toRawArray()), JsonSerializable objects, and objects with toArray() methods are recursively normalized for accurate change detection.
  • Scalar values (strings, integers, floats, booleans, null) continue to use direct comparison with an optimization when all entity attributes are scalars.

Previously, changing an object property or an array containing objects would not be detected as a change because only reference comparison was performed. Now, any modification to the internal state of objects or arrays will be properly detected. If you relied on the old shallow comparison behavior, you will need to update your code accordingly.

The Entity::toRawArray() method now properly converts arrays of entities when the $recursive parameter is true. Previously, properties containing arrays were not recursively processed. If you were relying on the old behavior where arrays remained unconverted, you will need to update your code.

  • Cache: The CacheInterface now includes the deleteMatching() method. If you've implemented your own caching driver from scratch, you will need to provide an implementation for this method to ensure compatibility.
  • Images: The ImageHandlerInterface now includes a new method: clearMetadata(). If you've implemented your own handler from scratch, you will need to provide an implementation for this method to ensure compatibility.
  • BaseModel: The type of the $row parameter for the cleanValidationRules() method has been changed from ?array $row = null to array $row.
  • PageCache: The PageCache filter constructor now accepts an optional Cache configuration parameter: __construct(?Cache $config = null). This allows dependency injection for testing purposes. While this is technically a breaking change if you extend the PageCache class with your own constructor, it should not affect most users as the parameter has a default value.
  • Added the SensitiveParameter attribute to various methods to conceal sensitive information from stack traces. Affected methods are:
    • CodeIgniter\Encryption\EncrypterInterface::encrypt()
    • CodeIgniter\Encryption\EncrypterInterface::decrypt()
    • CodeIgniter\Encryption\Handlers\OpenSSLHandler::encrypt()
    • CodeIgniter\Encryption\Handlers\OpenSSLHandler::decrypt()
    • CodeIgniter\Encryption\Handlers\SodiumHandler::encrypt()
    • CodeIgniter\Encryption\Handlers\SodiumHandler::decrypt()
    • CodeIgniter\HTTP\CURLRequest::setAuth()
    • CodeIgniter\HTTP\URI::setUserInfo()
    • CodeIgniter\Security\Security::derandomize()
  • Added native types to CacheInterface methods that were missing them. The following methods were updated:
    • initialize()
    • save()
    • delete()
    • increment()
    • decrement()
    • clean()
    • getCacheInfo()
    • getMetaData()
  • Added native return types to CodeIgniter\Debug\Toolbar methods:
    • prepare(): void
    • respond(): void
  • BaseModel: The deprecated method transformDataRowToArray() has been removed.
  • CodeIgniter: The deprecated CodeIgniter\CodeIgniter::resolvePlatformExtensions() has been removed.
  • Cache: The deprecated return type false for CodeIgniter\Cache\CacheInterface::getMetaData() has been replaced with null type.
  • IncomingRequest: The deprecated methods has been removed:
    • CodeIgniter\HTTP\IncomingRequest\detectURI()
    • CodeIgniter\HTTP\IncomingRequest\detectPath()
    • CodeIgniter\HTTP\IncomingRequest\parseRequestURI()
    • CodeIgniter\HTTP\IncomingRequest\parseQueryString()
  • IncomingRequest: The deprecated $config parameter has been removed from CodeIgniter\HTTP\IncomingRequest::setPath(), and the method visibility has been changed from public to private.
  • Text Helper: The deprecated types in random_string() function: basic, md5, and sha1 has been removed.
  • API Transformers: This new feature provides a structured way to transform data for API responses. See :ref:`API Transformers <api_transformers>` for details.
  • CLI: Added SignalTrait to provide unified handling of operating system signals in CLI commands.
  • Cache: Added async and persistent config item to Predis handler.
  • Cache: Added persistent config item to Redis handler.
  • Cache: Added support for HTTP status in ResponseCache.
  • Cache: Added Config\Cache::$cacheStatusCodes to control which HTTP status codes are allowed to be cached by the PageCache filter. Defaults to [] (all status codes for backward compatibility). Recommended value: [200] to only cache successful responses. See :ref:`Setting $cacheStatusCodes <web_page_caching_cache_status_codes>` for details.
  • CURLRequest: Added shareConnection config item to change default share connection.
  • CURLRequest: Added dns_cache_timeout option to change default DNS cache timeout.
  • CURLRequest: Added fresh_connect options to enable/disable request fresh connection.
  • DataConverter: Added EnumCast caster for database and entity.
  • Email: Added support for choosing the SMTP authorization method. You can change it via Config\Email::$SMTPAuthMethod option.
  • Image: The ImageMagickHandler has been rewritten to rely solely on the PHP imagick extension.
  • Image: Added ImageMagickHandler::clearMetadata() method to remove image metadata for privacy protection.
  • ResponseTrait: Added paginate` method to simplify paginated API responses. See :ref:`ResponseTrait::paginate() <api_response_trait_paginate>` for details.
  • Time: added methods Time::addCalendarMonths() and Time::subCalendarMonths()
  • Time: Added Time::isPast() and Time::isFuture() convenience methods. See :ref:`isPast <time-comparing-two-times-isPast>` and :ref:`isFuture <time-comparing-two-times-isFuture>` for details.
  • Exception Logging: All DB drivers now log database exceptions uniformly. Previously, each driver had its own log format.
  • MigrationRunner: Added distributed locking support to prevent concurrent migrations in multi-process environments. Enable with Config\Migrations::$lock = true.
  • UserAgents: Expanded the list of recognized robots with new search engine and service crawlers.
  • Added Email.invalidSMTPAuthMethod, Email.failureSMTPAuthMethod, CLI.signals.noPcntlExtension, CLI.signals.noPosixExtension and CLI.signals.failedSignal.
  • Deprecated Email.failedSMTPLogin and Image.libPathInvalid
  • Cookie: The CookieInterface::EXPIRES_FORMAT has been changed to D, d M Y H:i:s T to follow the recommended format in RFC 7231.
  • Format: Added support for configuring json_encode() maximum depth via Config\Format::$jsonEncodeDepth.
  • Paths: Added support for changing the location of the .env file via the Paths::$envDirectory property.
  • Toolbar: Added $disableOnHeaders property to app/Config/Toolbar.php.
  • Image:
    • The config property Config\Image::libraryPath has been deprecated. No longer used.
    • The exception method CodeIgniter\Images\Exceptions\ImageException::forInvalidImageLibraryPath has been deprecated. No longer used.
  • Cookie: The CookieInterface::SAMESITE_STRICT, CookieInterface::SAMESITE_LAX, and CookieInterface::SAMESITE_NONE constants are now written in ucfirst style to be consistent with usage in the rest of the framework.
  • Cache: Changed WincacheHandler::increment() and WincacheHandler::decrement() to return bool instead of mixed.
  • Toolbar: Fixed Maximum call stack size exceeded crash when AJAX-like requests (HTMX, Turbo, Unpoly, etc.) were made on pages with Debug Toolbar enabled.

See the repo's CHANGELOG.md for a complete list of bugs fixed.