Explorar o código

Avoid throwing an exception when the toString fails (#1868)

Vincent Langlet hai 1 ano
pai
achega
c4ba76aeae

+ 8 - 2
src/Monolog/Formatter/NormalizerFormatter.php

@@ -210,8 +210,14 @@ class NormalizerFormatter implements FormatterInterface
                 $accessor = new \ArrayObject($data);
                 $value = (string) $accessor['__PHP_Incomplete_Class_Name'];
             } elseif (method_exists($data, '__toString')) {
-                /** @var string $value */
-                $value = $data->__toString();
+                try {
+                    /** @var string $value */
+                    $value = $data->__toString();
+                } catch (\Throwable) {
+                    // if the toString method is failing, use the default behavior
+                    /** @var null|scalar|array<mixed[]|scalar|null> $value */
+                    $value = json_decode($this->toJson($data, true), true);
+                }
             } else {
                 // the rest is normalized by json encoding and decoding it
                 /** @var null|scalar|array<mixed[]|scalar|null> $value */

+ 17 - 3
tests/Monolog/Formatter/NormalizerFormatterTest.php

@@ -131,11 +131,25 @@ class NormalizerFormatterTest extends TestCase
     public function testFormatToStringExceptionHandle()
     {
         $formatter = new NormalizerFormatter('Y-m-d');
-        $this->expectException('RuntimeException');
-        $this->expectExceptionMessage('Could not convert to string');
-        $formatter->format($this->getRecord(context: [
+        $formatted = $formatter->format($this->getRecord(context: [
             'myObject' => new TestToStringError(),
         ]));
+        $this->assertEquals(
+            [
+                'level_name' => Level::Warning->getName(),
+                'level' => Level::Warning->value,
+                'channel' => 'test',
+                'message' => 'test',
+                'context' => [
+                    'myObject' => [
+                        TestToStringError::class => [],
+                    ],
+                ],
+                'datetime' => date('Y-m-d'),
+                'extra' => [],
+            ],
+            $formatted
+        );
     }
 
     public function testBatchFormat()