yii2-gii icon indicating copy to clipboard operation
yii2-gii copied to clipboard

Generator trim validator causes exception in PHP 8.1.9

Open nd4c opened this issue 2 years ago • 8 comments

What steps will reproduce the problem?

Using gii, try to Preview a Model.

What's expected?

The typical results with new model code and chance to see diff if there is a difference

What do you get instead?

PHP Deprecated Warning – [yii\base\ErrorException] (https://www.yiiframework.com/doc-2.0/yii-base-errorexception.html) trim(): Passing null to parameter #1 ($string) of type string is deprecated

in /var/www/html/nd4c_web/vendor/yiisoft/yii2/validators/FilterValidator.php at line 81

Additional info

This works in PHP 8.0.22, but fails in PHP 8.1.9

Debugging this I found that the following:

$model = yii\gii\generators\model\Generator $this->filter = trim $attribute = queryClass $value = null

In PHP 8.0 the $value of 'queryClass' is also null, but the trim filter does not cause an exception.

I believe this worked fine in earlier versions of PHP 8.1, but I don't know at what version it started.

If I select "Generate ActiveQuery" and the queryClass field becomes visible this works fine, because queryClass is not null.

Q A
Yii version 2.0.46
PHP version 8.1.9
Database version 10.3.34-MariaDB-0ubuntu0.20.04.1
Operating system Linux Mint 20.3 with Kernel Linux 5.15.0-46-generic

nd4c avatar Aug 30 '22 14:08 nd4c

I tried this on another computer running MInt 21 but with similar specs. It ran fine, then I ran composer update with a newer version of the composer.json file and it failed.

I was having problems with PHPUnit and changed my composer.json file - it is not the default settings for Yii2. These are the sections that changed: Previous:

"require": {
    "php": ">=8.0",
    "yiisoft/yii2": "~2.0.14",
    "yiisoft/yii2-bootstrap": "~2.0.0",
    "yiisoft/yii2-swiftmailer": "~2.1.0",
    "yiisoft/yii2-queue": "^2.1",
    "yiisoft/yii2-jui": "~2.0.0",
    "yiisoft/yii2-imagine": "~2.2.0",
    "mpdf/mpdf": "^8.0",
    "himiklab/yii2-colorbox-widget": "*",
    "slavkovrn/yii2-lightbox": "^1.0",
    "kekaadrenalin/yii2-imap": "dev-master",
    "2amigos/yii2-date-time-picker-widget" : "*",
    "2amigos/yii2-tinymce-widget": "*",
    "kartik-v/yii2-widget-datetimepicker": "*",
    "php-mime-mail-parser/php-mime-mail-parser": "^7.0",
    "yiisoft/yii2-symfonymailer": "^2.0"
},
"require-dev": {
    "yiisoft/yii2-debug": "~2.1.0",
    "yiisoft/yii2-gii": "~2.1.0",
    "yiisoft/yii2-faker": "~2.0.0",
    "codeception/codeception": "^4.0",
    "codeception/verify": "~0.5.0 || ~1.1.0",
    "codeception/specify": "~0.4.6",
    "symfony/browser-kit": ">=2.7 <=4.2.4",
    "codeception/module-filesystem": "^1.0.0",
    "codeception/module-yii2": "^1.0.0",
    "codeception/module-asserts": "^1.0.0",
    "rector/rector": "^0.12.12"
},

New:

"require": {
    "php": ">=8.0",
    "yiisoft/yii2": "~2.0.14",
    "yiisoft/yii2-bootstrap": "~2.0.0",
    "yiisoft/yii2-swiftmailer": "~2.1.0",
    "yiisoft/yii2-queue": "^2.1",
    "yiisoft/yii2-jui": "~2.0.0",
    "yiisoft/yii2-imagine": "~2.2.0",
    "mpdf/mpdf": "^8.0",
    "bower-asset/jquery-colorbox": "*",
    "kekaadrenalin/yii2-imap": "dev-master",
    "2amigos/yii2-date-time-picker-widget" : "*",
    "2amigos/yii2-tinymce-widget": "*",
    "kartik-v/yii2-widget-datetimepicker": "*",
    "php-mime-mail-parser/php-mime-mail-parser": "^7.0",
    "yiisoft/yii2-symfonymailer": "^2.0"
},
"require-dev": {
    "yiisoft/yii2-debug": "~2.1.0",
    "yiisoft/yii2-gii": "~2.1.0",
    "yiisoft/yii2-faker": "~2.0.0",
    "codeception/codeception": "^5.0.0-RC6",
    "codeception/verify": "~0.5.0 || ~1.1.0",
    "codeception/specify": "^2.0",
    "symfony/browser-kit": ">=2.7",
    "codeception/module-filesystem": "^3",
    "codeception/module-yii2": "^1.1.7",
    "codeception/module-asserts": "^3.0",
    "rector/rector": "^0.12.12"
},

I reverted my composer back to the older version, ran composer update, but I still get the exception in gii.

At this point I have no idea what the problem is...

nd4c avatar Aug 30 '22 14:08 nd4c

Try replacing "yiisoft/yii2-gii": "~2.1.0" with "yiisoft/yii2-gii": "~2.2.0" - your current constraint blocks update to the most recent version of yiisoft/yii2-gii.

rob006 avatar Aug 30 '22 18:08 rob006

Thanks. I did try that but I still get the same error if I do not select "Generate ActiveQuery" which leaves the queryClass field as null, because the form will not return it because it's disabled.

I tried a completely different project and matched the composer.json and it still works fine. So I'm guessing that I've done something in this project that's making PHP more strict in it's error handling - or I've broken the Yii error handler somehow.

Passing null to trim is a real PHP Deprecated Warning. I'm guessing my index.php entry script is too strict.

nd4c avatar Aug 30 '22 18:08 nd4c

Arrghhh! I have this in my site config file for dev: error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_NOTICE);

This project is very old since before 2011 (originally Yii1), and I've been caught several times by things deprecated suddenly disappearing...

But, seriously, Thanks for the gii version tip. I'd seen the newer version in newer projects and hadn't dawned on me that I should upgrade this project.

nd4c avatar Aug 30 '22 18:08 nd4c

My thinking is that the FilterValidator -> validateAttribute should check whether the filter is trim or not. Or have some way to handle or a mechanizm for null values and filters that cannot handle null. Some filters might just be skipped, some may need the null converted to a real value, and some might fail the filter on null.

nd4c avatar Aug 30 '22 19:08 nd4c

Actually the code calling the Filter Validator needs to be adjusted as per it's comments:

/**
 * FilterValidator converts the attribute value according to a filter.
 *
 * FilterValidator is actually not a validator but a data processor.
 * It invokes the specified filter callback to process the attribute value
 * and save the processed value back to the attribute. The filter must be
 * a valid PHP callback with the following signature:
 *
 * ```php
 * function foo($value) {
 *     // compute $newValue here
 *     return $newValue;
 * }
 * ```
 *
 * Many PHP functions qualify this signature (e.g. `trim()`).
 * If the callback function requires non-null argument (important since PHP 8.1)
 * remember to set [[skipOnEmpty]] to `true` otherwise you may trigger an error.
 *
 * To specify the filter, set [[filter]] property to be the callback.
 *
 * @author Qiang Xue <[email protected]>
 * @since 2.0
 */

nd4c avatar Aug 30 '22 19:08 nd4c

Solved by https://github.com/yiisoft/yii2/pull/19539

samdark avatar Sep 05 '22 21:09 samdark

Need to use trim validator instead of callback.

samdark avatar Sep 06 '22 06:09 samdark

https://github.com/yiisoft/yii2-gii/commit/c9efc088cd7003353125b2a2cc696d4b1028eafc

samdark avatar May 22 '23 20:05 samdark