Skip to content
Edit this page

Version 4.3.0

Release Date: January 10, 2023

4.3.0 release of CodeIgniter4

Highlights

  • Query Builder supports upsert(), upsertBatch(), deleteBatch() and now *batch() methods can set data from a query (contributed by sclubricants). See Query Builder.
  • Database Forge supports adding indexes to existing tables and naming indexes (contributed by sclubricants). See Forge.
  • To make the default configuration more secure, the default Validation Rules have been changed to Strict Rules.
  • When a database error occurs, the conditions under which an exception is thrown and the exception classes that can be thrown have been changed. See Exceptions when Database Errors Occur.

BREAKING

Behavior Changes

Exceptions when Database Errors Occur

  • The exceptions thrown by the database connection classes have been changed to CodeIgniter\Database\Exceptions\DatabaseException. Previously, different database drivers threw different exception classes, but these have been unified into DatabaseException.
  • The exceptions thrown by the execute() method of Prepared Queries have been changed to DatabaseException. Previously, different database drivers might throw different exception classes or not throw exceptions, but these have been unified into DatabaseException.
  • During transactions, exceptions are not thrown by default even if DBDebug is true.
  • DBDebug and CI_DEBUG Changes
    • To be consistent in behavior regardless of environments, Config\Database::$default['DBDebug'] and Config\Database::$tests['DBDebug'] have been changed to true by default. With these settings, an exception is always thrown when a database error occurs. Previously, it was false only in the production environment.
    • Now DatabaseException in BaseBuilder is thrown if $DBDebug is true. Previously, it was thrown if CI_DEBUG was true.
    • The default value of BaseConnection::$DBDebug has been changed to true.
    • With these changes, DBDebug now means whether or not to throw an exception when an error occurs. Although unrelated to debugging, the name has not been changed.
    • When running transactions with DBDebug set to true, even if a query error occurs, exceptions are not thrown by default. Previously, if a query error occurred, all the queries would be rolled back, and an exception would be thrown, so Managing Errors or Running Transactions Manually wouldn't work.
    • Now when you delete without a WHERE clause in Model, DatabaseException is thrown even if CI_DEBUG is false. Previously, it was thrown if CI_DEBUG was true.

HTTP Status Code and Exit Code when an Exception Occurs

Previously, CodeIgniter's Exception Handler used the Exception code as the HTTP status code in some cases, and calculated the Exit code based on the Exception code. However, there should be no logical connection between the Exception code and the HTTP status code or Exit code.

For example, the Exit code has changed as follows:

  • If an uncaught ConfigException occurs, the Exit code is EXIT_CONFIG (= 3) instead of 12.
  • If an uncaught CastException occurs, the Exit code is EXIT_CONFIG (= 3) instead of 9.
  • If an uncaught DatabaseException occurs, the Exit code is EXIT_DATABASE (= 8) instead of 17.

Time

The following methods of the Time class had bugs that changed the state of the current object:

  • add()
  • modify()
  • setDate()
  • setISODate()
  • setTime()
  • sub()

To fix these bugs, the Time class has been fixed:

  • Now the Time class extends DateTimeImmutable and is completely immutable.
  • The TimeLegacy class has been added for backward compatibility, which behaves the same as the unmodified Time class.

Others

  • Helper: script_tag() and safe_mailto() no longer output type="text/javascript" in the <script> tag.
  • CLI: The spark file has been changed due to a change in the processing of Spark commands.
  • CLI: CITestStreamFilter::$buffer = '' no longer causes the filter to be registered to listen for streams. Now there is a CITestStreamFilter::registration() method for this. See Capturing STDERR and STDOUT streams in Tests for details.
  • Database: InvalidArgumentException, which is a kind of LogicException, in BaseBuilder::_whereIn() is not suppressed by the configuration. Previously, if CI_DEBUG was false, the exception was suppressed.
  • Database: The data structure returned by BaseConnection::getForeignKeyData() has been changed.
  • Database: The CodeIgniter\Database\BasePreparedQuery class now returns a bool value for write-type queries instead of the Result class object.
  • Model: Model::update() method now raises a DatabaseException if it generates an SQL statement without a WHERE clause. Model does not support operations that update all records.
  • Routing: RouteCollection::resetRoutes() resets Auto-Discovery of Routes. Previously, once discovered, RouteCollection never discovered Routes files again even if RouteCollection::resetRoutes() was called.

Interface Changes

Note

As long as you have not extended the relevant CodeIgniter core classes or implemented these interfaces, all these changes are backward compatible and require no intervention.

OutgoingRequestInterface

  • Added new OutgoingRequestInterface that represents an outgoing request.
  • Added new OutgoingRequest class that implements OutgoingRequestInterface.
  • Now RequestInterface extends OutgoingRequestInterface.
  • Now CURLRequest extends OutgoingRequest.
  • Now Request extends OutgoingRequest.

Others

  • HTTP: Added missing getProtocolVersion(), getBody(), hasHeader() and getHeaderLine() methods in MessageInterface.
  • HTTP: Now ResponseInterface extends MessageInterface.
  • HTTP: Added missing ResponseInterface::getCSP() (and Response::getCSP()), ResponseInterface::getReasonPhrase() and ResponseInterface::getCookieStore() methods.
  • Database: Added missing CodeIgniter\Database\ResultInterface::getNumRows() method.
  • See also Validation Changes.

Method Signature Changes

Validation Changes

ValidationInterface

ValidationInterface has been changed to eliminate the mismatch between ValidationInterface and the Validation class.

  • The third parameter $dbGroup for ValidationInterface::run() has been added.
  • The following methods have been added to the interface:
    • ValidationInterface::setRule()
    • ValidationInterface::getRules()
    • ValidationInterface::getRuleGroup()
    • ValidationInterface::setRuleGroup()
    • ValidationInterface::loadRuleGroup()
    • ValidationInterface::hasError()
    • ValidationInterface::listErrors()
    • ValidationInterface::showError()
Validation

The return value of Validation::loadRuleGroup() has been changed from null to [] when the $group is empty.

Database

  • The return types of CodeIgniter\Database\BasePreparedQuery::close() and CodeIgniter\Database\PreparedQueryInterface have been changed to bool (previously untyped).
  • The return type of CodeIgniter\Database\Database::loadForge() has been changed to Forge.
  • The return type of CodeIgniter\Database\Database::loadUtils() has been changed to BaseUtils.
  • The parameter name $column in Table::dropForeignKey() has changed to $foreignName.
  • The second parameter $index of BaseBuilder::updateBatch() has changed to $constraints. It now accepts types array, string, or RawSql. Extending classes should likewise change types.
  • The $set parameter of BaseBuilder::insertBatch() and BaseBuilder::updateBatch() now accepts an object of a single row of data.
  • BaseBuilder::_updateBatch()
    • The second parameter $values has changed to $keys.
    • The third parameter $index has changed to $values. The parameter type has also changed to array.

Database Forge

  • The method signature of Forge::dropKey() has changed. An additional optional parameter $prefixKeyName has been added.
  • The method signature of Forge::addKey() has changed. An additional optional parameter $keyName has been added.
  • The method signature of Forge::addPrimaryKey() has changed. An additional optional parameter $keyName has been added.
  • The method signature of Forge::addUniqueKey() has changed. An additional optional parameter $keyName has been added.
  • The following method has an additional $asQuery parameter. When set to true, the method returns a standalone SQL query.
    • CodeIgniter\Database\Forge::_processPrimaryKeys()
  • In addition to the added $asQuery parameter above, the following methods also now return an array.
    • CodeIgniter\Database\Forge::_processIndexes()
    • CodeIgniter\Database\Forge::_processForeignKeys()

Others

  • API: The return type of API\ResponseTrait::failServerError() has been changed to ResponseInterface.
  • The following methods have been changed to accept ResponseInterface as a parameter instead of Response.
    • Debug\Exceptions::__construct()
    • Services::exceptions()
  • Request: The $index parameter of IncomingRequest::getJsonVar() now accepts an array, string or null value.

Enhancements

Commands

  • The call handler for Spark commands from the CodeIgniter\CodeIgniter class has been extracted. This will reduce the cost of console calls.
  • Added spark filter:check command to check the filters for a route. See Controller Filters for the details.
  • Added spark make:cell command to create a new Cell file and its view. See Generating Cell via Command for the details.
  • Now the spark routes command shows route names. See URI Routing.
  • Now the spark routes command can sort the output by Handler. See Sort by Handler.
  • Help information for a spark command can now be accessed using the --help option (e.g. php spark serve --help)
  • Added the CLI::promptByMultipleKeys() method to support multiple values in input, unlike promptByKey(). See promptByMultipleKeys() for details.
  • HTTP/3 is now considered a valid protocol.

Testing

  • Added the StreamFilterTrait to make it easier to work with capturing data from STDOUT and STDERR streams. See Testing CLI Output.
  • The CITestStreamFilter filter class now implements methods for adding a filter to streams. See Testing CLI Output.
  • Added the PhpStreamWrapper to make it easier to work with setting data to php://stdin. See Testing CLI Input.
  • Added method Timer::record() to measure performance in a callable. Also enhanced the common function timer() to accept an optional callable.
  • A boolean third parameter $useExactComparison is added to TestLogger::didLog() which sets whether log messages are checked verbatim. This defaults to true.
  • Added method CIUnitTestCase::assertLogContains() which compares log messages by parts instead of the whole of the message.

Database

Query Builder

  • Added upsert() and upsertBatch() methods to QueryBuilder. See Upserting Data.
  • Added deleteBatch() method to QueryBuilder. See DeleteBatch.
  • Added when() and whenNot() methods to conditionally add clauses to the query. See BaseBuilder::when() for details.
  • Improved the SQL structure for Builder::updateBatch(). See UpdateBatch for the details.
  • Added BaseBuilder::setQueryAsData() which allows insertBatch(), updateBatch(), upsertBatch(), deleteBatch() from a query. See insertBatch.

Forge

  • Added Forge::processIndexes() allowing the creation of indexes on an existing table. See Adding Keys to a Table for the details.
  • Added the ability to manually set index names. These methods include: Forge::addKey(), Forge::addPrimaryKey(), and Forge::addUniqueKey()
  • The new method Forge::dropPrimaryKey() allows dropping the primary key on a table. See Dropping a Primary Key.
  • Fixed Forge::dropKey() to allow dropping unique indexes. This required the DROP CONSTRAINT SQL command.
  • CodeIgniter\Database\Forge::addForeignKey() now includes a name parameter to set foreign key names manually. This is not supported in SQLite3.
  • SQLSRV now automatically drops DEFAULT constraint when using Forge::dropColumn().

Others

  • SQLite3 has a new Config item busyTimeout to set the timeout when a table is locked.
  • BaseConnection::escape() now excludes the RawSql data type. This allows passing SQL strings into data.
  • Improved data returned by BaseConnection::getForeignKeyData(). All DBMS return the same structure.
  • SQLite BaseConnection::getIndexData() can now return a pseudo index named PRIMARY for an AUTOINCREMENT column, and each returned index data has a type property.
  • BasePreparedQuery::close() now deallocates the prepared statement in all DBMS. Previously, they were not deallocated in Postgre, SQLSRV and OCI8. See close().
  • Added BaseConnection::transException() to throw exceptions during transactions. See Throwing Exceptions

Model

Libraries

Helpers and Functions

  • Now you can autoload helpers via app/Config/Autoload.php.
  • Added new Form helper functions validation_errors(), validation_list_errors() and validation_show_error() to display Validation Errors.
  • You can set the locale to route_to() if you pass a locale value as the last parameter.
  • Added request() and response() functions.
  • Added decamelize() function to convert camelCase to snake_case.
  • Added is_windows() global function to detect Windows platforms.

HTML5 Compatibility

Creation of void HTML elements like <input> can be configured to include or exclude the solidus character (/) before the right angle bracket (>) by setting the $html5 property in app/Config/DocTypes.php. If you set it to true, HTML5-compatible tags without / like <br> will be output.

The following items are affected:

  • Typography class: Creation of br tag
  • View Parser: The nl2br filter
  • Honeypot: input tag
  • Form helper
  • HTML helper
  • Common Functions

Error Handling

  • You can now log deprecation warnings instead of throwing exceptions. See Logging Deprecation Warnings for details.
  • Logging of deprecations is turned on by default.
  • To temporarily enable throwing of deprecations, set the environment variable CODEIGNITER_SCREAM_DEPRECATIONS to a truthy value.
  • Config\Logger::$threshold is now, by default, environment-specific. For the production environment, the default threshold is still 4, but it has changed to 9 for other environments.

Multiple Domain Support

  • Added Config\App::$allowedHostnames to set hostnames other than the hostname in the baseURL.
  • If you set Config\App::$allowedHostnames, URL-related functions such as base_url(), current_url(), site_url() will return the URL with the hostname set in Config\App::$allowedHostnames if the current URL matches.

Others

  • Routing: Added $routes->useSupportedLocalesOnly(true) so that the Router returns 404 Not Found if the locale in the URL is not supported in Config\App::$supportedLocales. See Localization
  • Routing: Added new $routes->view() method to return the view directly. See View Routes.
  • View: View Cells are now first-class citizens and can be located in the app/Cells directory. See View Cells.
  • View: Added Controlled Cells that provide more structure and flexibility to your View Cells. See View Cells for details.
  • Validation: Added Closure validation rule. See Using Closure Rule for details.
  • Config: Now you can specify Composer packages to auto-discover manually. See Code Modules.
  • Config: Added Config\Session class to handle session configuration.
  • Debug: Kint has been updated to 5.0.2.
  • Request: Added new $request->getRawInputVar() method to return a specified variable from the raw stream. See Retrieving Raw data.
  • Request: Added new $request->is() method to query the request type. See Determining Request Type.

Message Changes

  • Updated English language strings to be more consistent.
  • Added CLI.generator.className.cell and CLI.generator.viewName.cell.
  • Added en/Errors.php file.

Changes

  • Config
    • All atomic type properties in Config classes have been typed.
    • See Upgrading for information on changing the default values.
  • Changed the processing of Spark commands:
    • The CodeIgniter\CodeIgniter class no longer handles Spark commands.
    • The CodeIgniter::isSparked() method has been removed.
    • The CodeIgniter\CLI\CommandRunner class has been removed due to a change in Spark commands processing.
    • The system route configuration file system/Config/Routes.php has been removed.
    • The route configuration file app/Config/Routes.php has been changed. The include of the system routes configuration file was removed.

Deprecations

  • RouteCollection::localizeRoute() is deprecated.
  • RouteCollection::fillRouteParams() is deprecated. Use RouteCollection::buildReverseRoute() instead.
  • BaseBuilder::setUpdateBatch() and BaseBuilder::setInsertBatch() are deprecated. Use BaseBuilder::setData() instead.
  • The public property Response::$CSP is deprecated. It will be protected. Use Response::getCSP() instead.
  • CodeIgniter::$path and CodeIgniter::setPath() are deprecated. No longer used.
  • The public property IncomingRequest::$uri is deprecated. It will be protected. Use IncomingRequest::getUri() instead.
  • The public property IncomingRequest::$config is deprecated. It will be protected.
  • The method CLI::isWindows() is deprecated. Use is_windows() instead.
  • The Config\App session properties are deprecated in favor of the new session config class Config\Session.

Bugs Fixed

  • Fixed a bug where all types of Prepared Queries were returning a Result object instead of a bool value for write-type queries.
  • Fixed a bug with variable filtering in JSON requests using the IncomingRequest::getVar() or IncomingRequest::getJsonVar() methods.
  • Fixed a bug where the variable type could be changed when using a specified index with the IncomingRequest::getVar() or IncomingRequest::getJsonVar() methods.
  • Fixed a bug where the Honeypot field appeared when CSP was enabled. See also Honeypot and CSP.

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