note 94972 added to language.oop5.magic

From: Date: Sat, 05 Dec 2009 16:01:56 +0000
Subject: note 94972 added to language.oop5.magic
Groups: php.notes 
Request: Send a blank email to php-notes+get-163607@lists.php.net to get a copy of this message
This "tip" is for those who receive the error "Object of class X could not be converted to string" when __toString() is not possible, and it is not a choice to process or not - for example when received via debug_backtrace(). HOW IT HAPPENED: I use to have a logging function called LogEnter() and another called LogExit() that I use to call at every function when intensively debugging. For example all my functions look like: <?php function AnyFunction( $a, $b, $c ) { LogEnter(); // DoSomeStuffHere. LogExit(); } ?> Then inside LogEnter(), I use debug_backtrace() to discover the parameters that were used when calling the function (in this example the values of $a, $b, $c). The LogEnter() deals without knowing the number of parameters to treat, and formats something like ( 2, 3, 4 ) if those were the values. That info is printed among other info to a log-file. Doing this, keeps me with a single-very-simple way to trace all te calls. The thing is that if the the following are met at the same time, I have a problem: - The function accepts (and is called with) a class as a parameter. - The function is being debuggd by calling LogEnter(); - The class does not have __toString() coded. - For some reason I am not allowed to edit the class nor inherit from it. Then the debug function performs an "Object of class X could not be converted to string" error when trying to "dump" the parameter list (containing the object) into the file. LOG FUNCTION: This looks for the "parameters array" and then calls BuildArgs to format them. LogWrite finds the function name, file, line number, and so on, but does not matter here. <?php public function LogEnter() { $Debug = debug_backtrace(); $DebugLine = $Debug[ count( $Debug ) - 1 ]; $Args = isset( $DebugLine[ 'args' ] ) ? $DebugLine[ 'args' ] : '[x]'; $Msg = 'Entering with ' . BuildArgs( $Args ); LogWrite( $Msg ); } // CAUTION, THIS NEXT ONE FAILS private function BuildArgs( $Args ) { $Result = '( ' . implode( ', ', $Args ) . ' )'; return $Result; } ?> The problem is that if you call a function where a parameter being an object that has not the __toString() defined, then automatically "imploding" the argument list into a string, fails. SOLUTION: The solution is that the __toString is "checkable for its existance". The "tips" are to manually traverse the result of debug_backtrace()['args'] and then, for each element, check: - if it is or not an object with is_object( $Value ) - in case it is, check if __toString() is defined with method_exists( $Value, '__toString' ) - in case it is not an object or the method exist, perform a normal assignation. - in case it is an object without that method, print something else. I choose to output the class name with get_class( $Value ) and put it between square brackets. The final function becomes like this: <?php private function BuildArgs( $Args ) { // This function gets an 'args' array from debug_backtrace() and formats it in the printable format (a, b, c) including the parenthesis. $FormattedParams = ''; $Glue = ''; foreach( $Args as $Value ) { if( is_object( $Value ) ) { if( method_exists( $Value, "__toString" ) ) { $PrintableValue = $Value; } else { $PrintableValue = '[' . get_class( $Value ) . ']'; } } else { $PrintableValue = $Value; } $FormattedParams .= $Glue . $PrintableValue; $Glue = ', '; } $Result = sprintf( '( %s )', $FormattedParams ); return $Result; } ?> ---- Server IP: 69.147.83.197 Probable Submitter: 213.97.61.212 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.magic.php Edit -- https://master.php.net/note/edit/94972 Del: integrated -- https://master.php.net/note/delete/94972/integrated Del: useless -- https://master.php.net/note/delete/94972/useless Del: bad code -- https://master.php.net/note/delete/94972/bad+code Del: spam -- https://master.php.net/note/delete/94972/spam Del: non-english -- https://master.php.net/note/delete/94972/non-english Del: in docs -- https://master.php.net/note/delete/94972/in+docs Del: other reasons-- https://master.php.net/note/delete/94972 Reject -- https://master.php.net/note/reject/94972 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#163607) next »