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 to add indexes in the existing tables and name 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 that 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 intoDatabaseException.The exceptions thrown by the
execute()method of Prepared Queries have been changed toDatabaseException. Previously, different database drivers might throw different exception classes or did not throw exceptions, but these have been unified intoDatabaseException.During transactions, exceptions are not thrown by default even if
DBDebugis true.DBDebugandCI_DEBUGChangesTo be consistent in behavior regardless of environments,
Config\Database::$default['DBDebug']andConfig\Database::$tests['DBDebug']has been changed totrueby default. With these settings, an exception is always thrown when a database error occurs. Previously, it isfalseonly in the production environment.Now
DatabaseExceptionthrown inBaseBuilderis thrown if$DBDebugis true. Previously, it is thrown ifCI_DEBUGis true.The default value of
BaseConnection::$DBDebughas been changed totrue.With these changes,
DBDebugnow 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
DBDebugistrue, even if a query error occurs, exceptions are not thrown by default. Previously, if a query error occurs, all the queries will be rolled backed, and an exception will be thrown, so Managing Errors or Running Transactions Manually won’t work.Now when you delete without WHERE clause in
Model,DatabaseExceptionis thrown even ifCI_DEBUGis false. Previously, it is thrown ifCI_DEBUGis true.
HTTP Status Code and Exit Code when 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 with Exception code and HTTP Status Code or Exit code.
Now the Exception Handler sets HTTP status code to
500and set Exit code to the constantEXIT_ERROR(=1) by default.You can change HTTP status code or Exit code to implement
HTTPExceptionInterfaceorHasExitCodeInterfacein your Exception class. See Specify HTTP Status Code in Your Exception and Specify Exit Code in Your Exception.
For example, the Exit code has been changed like the following:
If an uncaught
ConfigExceptionoccurs, the Exit code isEXIT_CONFIG(=3) instead of12.If an uncaught
CastExceptionoccurs, the Exit code isEXIT_CONFIG(=3) instead of9.If an uncaught
DatabaseExceptionoccurs, the Exit code isEXIT_DATABASE(=8) instead of17.
Time
The following methods of the Time class had bugs that changed the state of the current object. To fix these bugs, the Time class has been fixed:
add()
modify()
setDate()
setISODate()
setTime()
sub()
Now the
Timeclass extendsDateTimeImmutableand is completely immutable.TimeLegacyclass has been added for backward compatibility, which behaves the same as the unmodifiedTimeclass.
Others
Helper:
script_tag()andsafe_mailto()no longer outputtype="text/javascript"in<script>tag.CLI: The
sparkfile 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 aCITestStreamFilter::registration()method for this. See Capturing STDERR and STDOUT streams in Tests for details.Database:
InvalidArgumentExceptionthat is a kind ofLogicExceptioninBaseBuilder::_whereIn()is not suppressed by the configuration. Previously ifCI_DEBUGwas false, the exception was suppressed.Database: The data structure returned by BaseConnection::getForeignKeyData() has been changed.
Database:
CodeIgniter\Database\BasePreparedQueryclass returns now a bool value for write-type queries instead of theResultclass object.Model:
Model::update()method now raises aDatabaseExceptionif 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 discover Routes files again even ifRouteCollection::resetRoutes()is 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
OutgoingRequestInterfacethat represents an outgoing request.Added new
OutgoingRequestclass that implementsOutgoingRequestInterface.Now
RequestInterfaceextendsOutgoingRequestInterface.Now
CURLRequestextendsOutgoingRequest.Now
RequestextendsOutgoingRequest.
Others
HTTP: Added missing
getProtocolVersion(),getBody(),hasHeader()andgetHeaderLine()method inMessageInterface.HTTP: Now
ResponseInterfaceextendsMessageInterface.HTTP: Added missing
ResponseInterface::getCSP()(andResponse::getCSP()),ResponseInterface::getReasonPhrase()andResponseInterface::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
$dbGroupforValidationInterface::run()has been added.The following methods are 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()andCodeIgniter\Database\PreparedQueryInterfacehave been changed tobool(previously untyped).The return type of
CodeIgniter\Database\Database::loadForge()has been changed toForge.The return type of
CodeIgniter\Database\Database::loadUtils()has been changed toBaseUtils.Parameter name
$columnhas changed inTable::dropForeignKey()to$foreignName.The second parameter
$indexofBaseBuilder::updateBatch()has changed to$constraints. It now accepts types array, string, orRawSql. Extending classes should likewise change types.The
$setparameter ofBaseBuilder::insertBatch()andBaseBuilder::updateBatch()now accepts an object of a single row of data.BaseBuilder::_updateBatch()The second parameter
$valueshas changed to$keys.The third parameter
$indexhas changed to$values. The parameter type also has changed toarray.
Database Forge
The method signature of
Forge::dropKey()has changed. An additional optional parameter$prefixKeyNamehas been added.The method signature of
Forge::addKey()has changed. An additional optional parameter$keyNamehas been added.The method signature of
Forge::addPrimaryKey()has changed. An additional optional parameter$keyNamehas been added.The method signature of
Forge::addUniqueKey()has changed. An additional optional parameter$keyNamehas been added.The following method has an additional
$asQueryparameter. When set totruethe method returns a stand alone SQL query.CodeIgniter\Database\Forge::_processPrimaryKeys()
In addition to the added
$asQueryparameter 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 toResponseInterface.The following methods have been changed to accept
ResponseInterfaceas a parameter instead ofResponse.Debug\Exceptions::__construct()Services::exceptions()
Request: The
$indexparameter ofIncomingRequest::getJsonVar()now accepts anarray,stringornullvalue.
Enhancements
Commands
The call handler for Spark commands from the
CodeIgniter\CodeIgniterclass has been extracted. This will reduce the cost of console calls.Added
spark filter:checkcommand to check the filters for a route. See Controller Filters for the details.Added
spark make:cellcommand to create a new Cell file and its view. See Generating Cell via Command for the details.Now
spark routescommand shows route names. See URI Routing.Now
spark routescommand can sort the output by Handler. See Sort by Handler.Help information for a spark command can now be accessed using the
--helpoption (e.g.php spark serve --help)Added methods
CLI::promptByMultipleKeys()to support multiple value in input, unlikepromptByKey(). See promptByMultipleKeys() for details.HTTP/3 is now considered a valid protocol.
Testing
Added the
StreamFilterTraitto 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
PhpStreamWrapperto make it easier to work with setting data tophp://stdin. See Testing CLI Input.Added method Timer::record() to measure performance in a callable. Also enhanced common function
timer()to accept optional callable.A boolean third parameter
$useExactComparisonis added toTestLogger::didLog()which sets whether log messages are checked verbatim. This defaults totrue.Added method
CIUnitTestCase::assertLogContains()which compares log messages by parts instead of the whole of the message.
Database
Query Builder
Added
upsert()andupsertBatch()methods to QueryBuilder. See Upserting Data.Added
deleteBatch()method to QueryBuilder. See $builder->deleteBatch().Added
when()andwhenNot()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 allowsinsertBatch(),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(), andForge::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 theDROP CONSTRAINTSQL 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
DEFAULTconstraint when using Forge::dropColumn().
Others
SQLite3 has a new Config item
busyTimeoutto set timeout when a table is locked.BaseConnection::escape()now excludes theRawSqldata type. This allows passing SQL strings into data.Improved data returned by BaseConnection::getForeignKeyData(). All DBMS returns the same structure.
SQLite BaseConnection::getIndexData() now can return pseudo index named
PRIMARYfor AUTOINCREMENT column, and each returned index data hastypeproperty.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 exceptinons during transactions. See Throwing Exceptions
Model
Added before and after events to
BaseModel::insertBatch()andBaseModel::updateBatch()methods. See Working with Query Builder.Added
Model::allowEmptyInserts()method to insert empty data. See Using CodeIgniter’s ModelAdded new Property Casting class
IntBoolCastfor Entity.
Libraries
Publisher: Added methods
replace(),addLineAfter()andaddLineBefore()to modify files in Publisher. See Publisher for details.Encryption: Now Encryption can decrypt data encrypted with CI3’s Encryption. See Configuration to Maintain Compatibility with CI3.
CURLRequest: Added option version HTTP2 in CURLRequest.
Helpers and Functions
Now you can autoload helpers by app/Config/Autoload.php.
Added new Form helper function
validation_errors(),validation_list_errors()andvalidation_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()andresponse()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 exclude or not 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
brtagView Parser: The
nl2brfilterHoneypot:
inputtagForm 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_DEPRECATIONSto a truthy value.Config\Logger::$thresholdis now, by default, environment-specific. For production environment, default threshold is still4but changed to9for other environments.
Multiple Domain Support
Added
Config\App::$allowedHostnamesto set hostnames other than the hostname in the baseURL.If you set
Config\App::$allowedHostnames, URL-related functions such asbase_url(),current_url(),site_url()will return the URL with the hostname set inConfig\App::$allowedHostnamesif 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 inConfig\App::$supportedLocales. See LocalizationRouting: 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 Cellsthat 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\Sessionclass 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 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.cellandCLI.generator.viewName.cell.Added en/Errors.php file.
Changes
- Config
All atomic type properties in
Configclasses have been typed.See Upgrading for information on changing the default values.
- Changed the processing of Spark commands:
The
CodeIgniter\CodeIgniterno longer handles Spark commands.The
CodeIgniter::isSparked()method has been removed.The
CodeIgniter\CLI\CommandRunnerclass has been removed due to a change in Spark commands processing.The system route configuration file
system/Config/Routes.phphas been removed.The route configuration file
app/Config/Routes.phphas been changed. Removed include of system routes configuration file.
Deprecations
RouteCollection::localizeRoute()is deprecated.RouteCollection::fillRouteParams()is deprecated. UseRouteCollection::buildReverseRoute()instead.BaseBuilder::setUpdateBatch()andBaseBuilder::setInsertBatch()are deprecated. UseBaseBuilder::setData()instead.The public property
Response::$CSPis deprecated. It will be protected. UseResponse::getCSP()instead.CodeIgniter::$pathandCodeIgniter::setPath()are deprecated. No longer used.The public property
IncomingRequest::$uriis deprecated. It will be protected. UseIncomingRequest::getUri()instead.The public property
IncomingRequest::$configis deprecated. It will be protected.The method
CLI::isWindows()is deprecated. Useis_windows()instead.The
Config\Appsession properties in favor of the new session config classConfig\Session.
Bugs Fixed
Fixed a bug when all types of
Prepared Querieswere returning aResultobject instead of a bool value for write-type queries.Fixed a bug with variable filtering in JSON requests using with
IncomingRequest::getVar()orIncomingRequest::getJsonVar()methods.Fixed a bug when variable type may be changed when using a specified index with
IncomingRequest::getVar()orIncomingRequest::getJsonVar()methods.Fixed a bug that Honeypot field appears when CSP is enabled. See also Honeypot and CSP.
See the repo’s CHANGELOG.md for a complete list of bugs fixed.