run code in 300+ PHP versions simultaneously
<?php // // The goal is to try to safely cast an object to string but only if it can reasonably // be assumed to be stringable. (properly implements __toString) // // This is as close as I've been able to come to ensure that bad things do not get // called and I only deal with proper string results. // // The only major edge case here is that without implementing reflection it is // impossible to know if __toString was implemented as a static method. This // is a bummer but I'm willing to call this one "good enough." // class HasValidToString { public function __toString() { return 'Object\'s __toString is valid'; } } class HasNonPublicToString { protected function __toString() { return 'has non public __toString'; } } class HasNullToStringReturnValue { public static function __toString() { } } class HasNumberReturnValue { public function __toString() { return 5; } } class HasObjectReturnValue { public function __toString() { return new HasValidToString(); } } // Do to PHP's fuzzy nature on how to handle things like this, you'll get a warning that // this method should not be static but it will happily let you call it on an object // instance so even though you might say that this is expected to fail it actually // won't. Chances are something else awful will happen, though. Short of dipping // into Reflection I'm not sure how to guard against this such that we do not // call into a static __toString method. class HasStaticToString { public static function __toString() { return 'Object\'s __toString is static; should not be able to call it'; } } $isExpectedToPass = true; $isExpectedToFail = false; function safely_cast_object_to_string($object) { if (! method_exists($object, '__toString')) { throw new InvalidArgumentException('Object has no __toString'); } if (! is_callable([$object, '__toString'])) { throw new InvalidArgumentException('Object\'s __toString is not callable'); } $string = $object->__toString(); if (! is_string($string)) { throw new InvalidArgumentException('Object\'s __toString does not return a string value'); } return $string; } foreach ([ [new HasValidToString(), $isExpectedToPass], [new HasNonPublicToString(), $isExpectedToFail], [new HasNullToStringReturnValue(), $isExpectedToFail], [new HasNumberReturnValue(), $isExpectedToFail], [new HasObjectReturnValue(), $isExpectedToFail], [new HasStaticToString(), $isExpectedToFail], // it actually passes... ] as $test) { list ($sample, $expectation) = $test; $actual = false; $string = null; $message = ''; try { $string = safely_cast_object_to_string($sample); $actual = true; } catch (\InvalidArgumentException $e) { $message = $e->getMessage(); } printf( "%26s [%s] %s\n", get_class($sample), $actual === $expectation ? 'PASS' : 'FAIL', ! is_null($string) ? $string : $message ); }
Output for git.master, git.master_jit, rfc.property-hooks
Warning: The magic method HasNonPublicToString::__toString() must have public visibility in /in/nsetu on line 16 Fatal error: Method HasNullToStringReturnValue::__toString() cannot be static in /in/nsetu on line 17
Process exited with code 255.

This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.

Active branches

Archived branches

Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page

47.66 ms | 402 KiB | 8 Q