The answer is non-printable characters. In the conversion of Objects to Arrays, and their various Properties to Strings, these Strings contain non-printing control characters that we never see, but as they exist, break PHP's error_log()
.
The solution is a rather simple, but essential:
$data= preg_replace('/[^\x0A\x20-\x7E\xC0-\xD6\xD8-\xF6\xF8-\xFF]/','',$data);
// Or to preserve extended characters, use the below expression.
// Mind you many of these still may not display correctly in logs.
$data= preg_replace('/(?!\n)[[:cntrl:]]+/','',$data);
Called before sending the $message to the Error Log, this removes many non-printing characters while preserving many characters other pregs I found removed. Just in case you need them:
\x0A = [newline]
\x20-\x7E = [space] ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
\xC0-\xD6 = À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö
\xD8-\xF6 = Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö
\xF8-\xFF = ø ù ú û ü ý þ ÿ
In the end, there was some additional rewriting to isolate some functionality for use elsewhere, but the ultimate solution is as simple.
EDIT: Upon further review, it seems this is more specifically related to Bug #64439 - "\0 causes error_log strings to be truncated".
For those wondering, \0 (or \x00 or \x0) is the NULL character, and in the particular above case, is a result of the Casting of the Object as an Array, which returns a Key value of NULL.classname.NULL.propname
.