mirror of
https://github.com/yiisoft/yii2.git
synced 2025-10-30 18:17:00 +08:00
Fix #20348: ErrorHandler::convertExceptionToError() Passing E_USER_ERROR to trigger_error() is deprecated since PHP 8.4
This commit is contained in:
@ -26,6 +26,7 @@ Yii Framework 2 Change Log
|
|||||||
- Enh #20413: Add PHPStan/Psalm annotations for `Action`, `ActionEvent`, `Application`, `DynamicModel` and `InlineAction` (max-s-lab)
|
- Enh #20413: Add PHPStan/Psalm annotations for `Action`, `ActionEvent`, `Application`, `DynamicModel` and `InlineAction` (max-s-lab)
|
||||||
- Enh #20416: Add `PHPStan`/`PSalm` annotation for `owner` property in `Behavior` class (terabytesoftw)
|
- Enh #20416: Add `PHPStan`/`PSalm` annotation for `owner` property in `Behavior` class (terabytesoftw)
|
||||||
- Bug #20423: `strcmp()` Passing `null` to parameter `2` ($string2) of type string is deprecated (terabytesoftw)
|
- Bug #20423: `strcmp()` Passing `null` to parameter `2` ($string2) of type string is deprecated (terabytesoftw)
|
||||||
|
- Bug #20348: `ErrorHandler::convertExceptionToError()` Passing `E_USER_ERROR` to `trigger_error()` is deprecated since PHP `8.4` (terabytesoftw)
|
||||||
|
|
||||||
|
|
||||||
2.0.52 February 13, 2025
|
2.0.52 February 13, 2025
|
||||||
|
|||||||
@ -51,6 +51,41 @@ if you want to upgrade from version A to version C and there is
|
|||||||
version B between A and C, you need to follow the instructions
|
version B between A and C, you need to follow the instructions
|
||||||
for both A and B.
|
for both A and B.
|
||||||
|
|
||||||
|
Upgrade from Yii 2.0.53
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* `ErrorHandler::convertExceptionToError()` has been deprecated and will be removed in version 22.0.
|
||||||
|
|
||||||
|
This method was deprecated due to `PHP 8.4` deprecating the use of `E_USER_ERROR` with `trigger_error()`.
|
||||||
|
The framework now handles exceptions in `__toString()` methods more appropriately based on the PHP version.
|
||||||
|
|
||||||
|
**Before (deprecated):**
|
||||||
|
```php
|
||||||
|
public function __toString() {
|
||||||
|
try {
|
||||||
|
return $this->render();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
ErrorHandler::convertExceptionToError($e);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After (recommended):**
|
||||||
|
```php
|
||||||
|
public function __toString() {
|
||||||
|
try {
|
||||||
|
return $this->render();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
if (PHP_VERSION_ID < 70400) {
|
||||||
|
trigger_error(ErrorHandler::convertExceptionToString($e), E_USER_ERROR);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Upgrade from Yii 2.0.52
|
Upgrade from Yii 2.0.52
|
||||||
-----------------------
|
-----------------------
|
||||||
* There was a bug when loading fixtures into PostgreSQL database, the table sequences were not reset. If you used a work-around or if you depended on this behavior, you are advised to review your code.
|
* There was a bug when loading fixtures into PostgreSQL database, the table sequences were not reset. If you used a work-around or if you depended on this behavior, you are advised to review your code.
|
||||||
|
|||||||
@ -378,6 +378,11 @@ abstract class ErrorHandler extends Component
|
|||||||
* to PHP errors because exceptions cannot be thrown inside of them.
|
* to PHP errors because exceptions cannot be thrown inside of them.
|
||||||
* @param \Throwable $exception the exception to convert to a PHP error.
|
* @param \Throwable $exception the exception to convert to a PHP error.
|
||||||
* @return never
|
* @return never
|
||||||
|
*
|
||||||
|
* @deprecated since 2.0.53. Use conditional exception throwing in `__toString()` methods instead.
|
||||||
|
* For PHP < 7.4: use `trigger_error()` directly with `convertExceptionToString()` method.
|
||||||
|
* For PHP >= 7.4: throw the exception directly as `__toString()` supports exceptions.
|
||||||
|
* This method will be removed in 2.2.0.
|
||||||
*/
|
*/
|
||||||
public static function convertExceptionToError($exception)
|
public static function convertExceptionToError($exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -59,9 +59,14 @@ abstract class BaseMessage extends BaseObject implements MessageInterface
|
|||||||
// use trigger_error to bypass this limitation
|
// use trigger_error to bypass this limitation
|
||||||
try {
|
try {
|
||||||
return $this->toString();
|
return $this->toString();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
ErrorHandler::convertExceptionToError($e);
|
if (PHP_VERSION_ID < 70400) {
|
||||||
return '';
|
trigger_error(ErrorHandler::convertExceptionToString($e), E_USER_ERROR);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,12 +174,14 @@ class ActiveField extends Component
|
|||||||
// use trigger_error to bypass this limitation
|
// use trigger_error to bypass this limitation
|
||||||
try {
|
try {
|
||||||
return $this->render();
|
return $this->render();
|
||||||
} catch (\Exception $e) {
|
|
||||||
ErrorHandler::convertExceptionToError($e);
|
|
||||||
return '';
|
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
ErrorHandler::convertExceptionToError($e);
|
if (PHP_VERSION_ID < 70400) {
|
||||||
return '';
|
trigger_error(ErrorHandler::convertExceptionToString($e), E_USER_ERROR);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,54 @@ class BaseMessageTest extends TestCase
|
|||||||
$message = $mailer->compose();
|
$message = $mailer->compose();
|
||||||
$this->assertEquals($message->toString(), '' . $message);
|
$this->assertEquals($message->toString(), '' . $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExceptionToString()
|
||||||
|
{
|
||||||
|
if (PHP_VERSION_ID < 70400) {
|
||||||
|
$this->markTestSkipped('This test is for PHP 7.4+ only');
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = new TestMessageWithException();
|
||||||
|
|
||||||
|
$this->expectException(\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Test exception in toString.');
|
||||||
|
|
||||||
|
(string) $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionToStringLegacy()
|
||||||
|
{
|
||||||
|
if (PHP_VERSION_ID >= 70400) {
|
||||||
|
$this->markTestSkipped('This test is for PHP < 7.4 only');
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = new TestMessageWithException();
|
||||||
|
|
||||||
|
$errorTriggered = false;
|
||||||
|
$errorMessage = '';
|
||||||
|
|
||||||
|
set_error_handler(
|
||||||
|
function ($severity, $message, $file, $line) use (&$errorTriggered, &$errorMessage) {
|
||||||
|
if ($severity === E_USER_ERROR) {
|
||||||
|
$errorTriggered = true;
|
||||||
|
$errorMessage = $message;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
E_USER_ERROR,
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = (string) $message;
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
$this->assertTrue($errorTriggered, 'E_USER_ERROR should have been triggered');
|
||||||
|
$this->assertStringContainsString('Test exception in toString.', $errorMessage);
|
||||||
|
$this->assertSame('', $result, 'Result should be an empty string');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,3 +226,11 @@ class TestMessage extends BaseMessage
|
|||||||
return get_class($this);
|
return get_class($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestMessageWithException extends TestMessage
|
||||||
|
{
|
||||||
|
public function toString()
|
||||||
|
{
|
||||||
|
throw new \Exception('Test exception in toString.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ use yii\widgets\MaskedInput;
|
|||||||
class ActiveFieldTest extends \yiiunit\TestCase
|
class ActiveFieldTest extends \yiiunit\TestCase
|
||||||
{
|
{
|
||||||
use ArraySubsetAsserts;
|
use ArraySubsetAsserts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ActiveFieldExtend
|
* @var ActiveFieldExtend
|
||||||
*/
|
*/
|
||||||
@ -700,6 +700,54 @@ HTML;
|
|||||||
$this->assertStringContainsString('placeholder="pholder_both_direct"', (string) $widget);
|
$this->assertStringContainsString('placeholder="pholder_both_direct"', (string) $widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExceptionToString()
|
||||||
|
{
|
||||||
|
if (PHP_VERSION_ID < 70400) {
|
||||||
|
$this->markTestSkipped('This test is for PHP 7.4+ only');
|
||||||
|
}
|
||||||
|
|
||||||
|
$field = new TestActiveFieldWithException();
|
||||||
|
|
||||||
|
$this->expectException(\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Test exception in toString.');
|
||||||
|
|
||||||
|
(string) $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionToStringLegacy()
|
||||||
|
{
|
||||||
|
if (PHP_VERSION_ID >= 70400) {
|
||||||
|
$this->markTestSkipped('This test is for PHP < 7.4 only');
|
||||||
|
}
|
||||||
|
|
||||||
|
$field = new TestActiveFieldWithException();
|
||||||
|
|
||||||
|
$errorTriggered = false;
|
||||||
|
$errorMessage = '';
|
||||||
|
|
||||||
|
set_error_handler(
|
||||||
|
function ($severity, $message, $file, $line) use (&$errorTriggered, &$errorMessage) {
|
||||||
|
if ($severity === E_USER_ERROR) {
|
||||||
|
$errorTriggered = true;
|
||||||
|
$errorMessage = $message;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
E_USER_ERROR,
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = (string) $field;
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
$this->assertTrue($errorTriggered, 'E_USER_ERROR should have been triggered');
|
||||||
|
$this->assertStringContainsString('Test exception in toString.', $errorMessage);
|
||||||
|
$this->assertSame('', $result, 'Result should be an empty string');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods.
|
* Helper methods.
|
||||||
*/
|
*/
|
||||||
@ -811,3 +859,11 @@ class TestMaskedInput extends MaskedInput
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestActiveFieldWithException extends ActiveField
|
||||||
|
{
|
||||||
|
public function render($content = null)
|
||||||
|
{
|
||||||
|
throw new \Exception('Test exception in toString.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user