log icon indicating copy to clipboard operation
log copied to clipboard

Message::parse() not replacing multiple placeholders from context

Open technicated opened this issue 1 month ago • 1 comments

Description

A message which contains more than one placeholders is not logged correctly, leaving all placeholders in place and only showing the relevant data in the context.

For example:

$logger = new Logger([new StreamTarget()]);
$logger->info('placeholder1: {p1} - placeholder2: {p2}', ['p1' => 'hello', 'p2' => 'world']);
$logger->flush();

// expected:
// 2026-01-14 10:19:04.022900 [info][application] placeholder1: hello - placeholder2: world
//
// Message context:
//
// trace:
// ...
// p1: 'hello'
// p2: 'world'

// actual:
// 2026-01-14 10:19:04.022900 [info][application] placeholder1: {p1} - placeholder2: {p2}
//
// Message context:
//
// trace:
// ...
// p1: 'hello'
// p2: 'world'

I suspect the issue being in Message::parse(), which uses preg_replace_callback with regex '/{(.*)}/' which is eager instead of '/{(.*?)}/', which is instead lazy, causing the match to always be a single one in the format p1} - placeholder2 {p2.

I quickly looked in the tests and there seems not to be one for this exact scenario, maybe it might also be added.

If this bug is confirmed I will happily fork the repo and submit a patch! Thanks everybody for all your work on Yii!

Package version

2.1.1

PHP version

8.3.6

technicated avatar Jan 14 '26 10:01 technicated