note 94972 added to language.oop5.magic
| From: | xmontero at dsitelecom dot com | 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