Due to overwhelming support from the community, October CMS is updating its foundation framework to the latest Long Term Support (LTS) release. As a result, there are some new requirements to run October and some code changes required.
This guide is intented to help understand the changes associated from upgrade to Laravel 6 as the foundation framework used by October CMS.
Affected functionality
If you are using any of the following functionality it's highly recommended that you take a look at the relevant section in this guide and make any required changes to your usage:
- Configuration Files (
/config/*.php
) - Environment Variables (
.env
files) - Any Packages Made for Laravel
- Laravel Package Auto-Discovery
- Interacting with
Cache
Repositories - String Based Primary Keys in Models
- Use of
$guarded
in Models - Wildcard Event Listeners
- Catch-all Routing
- Using Carbon Directly
- Using Jenssegers\Date Directly
- Using Symfony Directly
- Using League\Csv Directly
- Unit Testing
Configuration Files (config/*
files)
Some new configuration files have been made available as part of the Laravel 6 upgrade. You should check these configuration files to your project's config
folder, and adjust the configuration as necessary.
Environment Variables (.env
files)
If you are using .env
files with a variable that has a #
inside of an unquoted value; that will now be treated as a comment due to an upgrade to the phpdotenv
library used for parsing them.
If you have any #
characters inside of unquoted environment variables please update them to be quoted instead (ex. DB_PASS=23das#sdfas
must be updated to DB_PASS="23das#sdfas"
).
Additionally, putenv()
no longer changes the value returned by calls to env()
as the env
helper is now considered read-only. If dynamically changing configuration is required, it is recommended to use Config values instead as they can be dynamically changed with Config::set()
Note:
.env
files now require any values with spaces in them to be quoted too, it's recommended to just enclose every single value in.env
with double quotes.
Using any Laravel Based Packages
The version of Laravel has been changed from 5.5 LTS to 6.x LTS. If you are using packages made for Laravel you may have to go through and update them to a version compatible with Laravel 6.x.
Interacting with Cache Repositories Directly
Cache TTL (time-to-live) values that are specified as an integer are treated as seconds now, as opposed to minutes, when interacting directly with a cache repository. If you interact with the cache directly, we recommend that you use DateTime
or Carbon
instances to define when your data is to expire (ex. now()->addMinutes(60)
instead of 60
). If you wish to continue using integers, you will need to multiply your integer values by 60 to get the number of seconds.
String-based Primary Keys in Models
If you are using string based primary keys for your models add protected $keyType = 'string';
to the model class definition to prevent performance optimizations meant for integer key types from negatively affecting your code.
Use of $guarded
in Models
Due to a recent security patch made in the Laravel framework (see discussion), if a model uses the $guarded
property to define attributes that are to be protected from mass assignment, then any attempts to use mass-assignment to populate a property / attribute of the model that does not exist in the database will fail. Example:
MyModel extends Model
{
$guarded = ['id'];
$someProperty = null;
public function setSomePropertyAttribute($value)
{
$this->someProperty = $value
}
}
Calling MyModel::create(['someProperty' => 'data']);
would previously have worked, but will not anymore.
This specifically affected the October\Rain\Database\Attach\File
model (and by extension, the System\Models\File
model), which now use the "fillable" attributes property to define the fields available for mass assignment, as opposed to the "guarded" attributes property.
If you extend either of these models to provide your own custom File model and wish to have extra fields stored through mass assignment, you will need to copy the $fillable
attribute from the October\Rain\Database\Attach\File
model and place it in your own extension, adding any extra fields that you wish to be fillable as well.
Wildcard event listeners: Event::listen('example.*', $listener);
The parameters sent to wildcard event listeners in October has changed to match what Laravel has done since 5.4. This was overlooked in the 5.5 update but is being applied now. Going forward all wildcard event listeners will receive the name of the event currently being fired as the first parameter and an array of the event arguments as the second parameter.
Example of old wildcard listener:
Event::listen('*', function ($params) {
if (Event::firing() === 'some.specific.event') {
// do stuff with $params
}
});
Example of new wildcard listener:
Event::listen('*', function ($event, $params) {
if ($event === 'some.specific.event') {
// do stuff with $params
}
});
Catch-all routing
Changes to the routing in Laravel 6 have resulted in the behaviour of catch-all routes being changed in October CMS. Previously, a catch-all route could be defined with the following:
Route::any('{slug}', 'Backend\Classes\BackendController@run')->where('slug', '(.*)?');
The definition {slug}
in Laravel 6 is now considered to be a required URL parameter, and will fail with an exception if the router sees an empty parameter. If your plugin uses a similar routing rule, and you would like URLs with an empty parameter to still be routed to your plugin, you must change this definition to be optional by suffixing the parameter name with the question mark (?
) symbol. Eg:
Route::any('{slug?}', 'Backend\Classes\BackendController@run')->where('slug', '(.*)?');
This can be done immediately for your plugin routes, as optional parameters were already available in Laravel 5.5.
Using Carbon directly
The Carbon library has been upgraded from version 1 to version 2. While this should mostly work with existing code, please review the upgrade guide.
Using Jenssegers/Date directly
The jenssegers/date
library has been removed from October entirely as most of its functionality is now present in Carbon 2.0. This should mostly work with existing code unless you were referencing it directly, in which case replace any references to Jenssegers\Date\Date
with October\Rain\Argon\Date
.
Using Symfony directly
Symfony has been upgraded to version 4 (except for the Yaml subsystem). If interacting directly with it, please review the upgrade guide
Using League CSV directly
The CSV package provided by The PHP League has been upgraded from version 8 to version 9. We have made the necessary adjustments to October CMS in order to accommodate this change, however, if you use the library directly or have extended the ImportModel
and ExportModel
classes, it is strongly recommended that you review the upgrade guide as several methods have been dropped or moved.
Unit Testing
If your plugin contains unit tests, you will need to make some adjustments to your unit tests in order to function with the Laravel 6 upgrade.
- All
setUp
andtearDown
methods in your unit test classes must now have the return typevoid
specified to match PHPUnit 8's requirements.- Change all
public function setUp()
methods topublic function setUp(): void
. - Change all
public function tearDown()
methods topublic function tearDown(): void
.
- Change all
- The
syntaxCheck
attribute for the<phpunit>
tag in yourphpunit.xml
file is now deprecated. This should be removed from yourphpunit.xml
file.
In addition to the changes above, note the following deprecations in PHPUnit 8 - these will be thrown as warnings in your unit tests.
- The
@expectedException
group of docblock annotations are now deprecated. Instead, you should call the following methods inside your unit test method, depending on the annotation:- @expectedException:
$this->expectException(ClassName::class)
- @expectedExceptionCode:
$this->expectExceptionCode(int)
- @expectedExceptionMessage:
$this->expectExceptionMessage(string)
- @expectedException:
- The
assertInternalType()
method is no longer available. Instead, you should use thearrayIs[Type]()
methods, whereType
is the PHP variable type with a capital letter. For example, instead ofassertInternalType('string', ...)
, you should useassertIsString
, orassertInternalType('array', ...)
should beassertIsArray
. - The
assertContains()
method no longer tests whether strings are inside strings - it now will only detect if an item is contained in an array. If you are usingassertContains()
in this fashion, you should instead useassertStringContainsString()
.
For more information on deprecations, see the PHPUnit 8 release notes. Note that although the assertArraySubset()
method was deprecated, we are still maintaining the method through requiring the dms/phpunit-arraysubset-asserts
library, so you may continue to use that assertion.
Further Reading
Laravel Upgrade Guides
Package Upgrade Guides
PHP Upgrade Guides
Migrating from PHP 7.0 to PHP 7.1
Migrating from PHP 7.1 to PHP 7.2
Migrating from PHP 7.2 to PHP 7.3
Migrating from PHP 7.3 to PHP 7.4