Skip to content

Instantly share code, notes, and snippets.

@nyamsprod
Last active October 4, 2016 09:31
Show Gist options
  • Save nyamsprod/10adbef7926dbc449e01eaa58ead5feb to your computer and use it in GitHub Desktop.
Save nyamsprod/10adbef7926dbc449e01eaa58ead5feb to your computer and use it in GitHub Desktop.
Property exists recursive version
<?php
/**
* Tell whether the propety or the inner property exists
* we do not use isset as isset($obj->foo->bar->baz) would return false
* if $obj->foo->bar->baz = null
*
* Usage:
*
* if (property_exists($obj, 'foo->bar->baz')) {
* echo $obj->foo->bar->baz;
* }
*
* @param object $object a PHP object
* @param string $path the property path
* @param string $separator the property separator by default '->' is used
*
* @return bool
*/
function property_exists_recursive($object, string $path, string $separator = '->'): bool
{
if (!is_object($object)) {
return false;
}
$properties = explode($separator, $path);
$property = array_shift($properties);
if (!property_exists($object, $property)) {
return false;
}
try {
$object = $object->$property;
} catch (Throwable $e) {
return false;
}
if (empty($properties)) {
return true;
}
return property_exists_recursive($object, implode('->', $properties));
}
/// TEST
// Create a handler function
$assert_handler = function ($file, $line, $code, $desc = null)
{
echo "Assertion failed";
if (isset($desc) && '' !== $desc) {
echo ": $desc";
}
echo PHP_EOL;
};
// Set up the callback
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
assert_options(ASSERT_CALLBACK, $assert_handler);
// Simple stdClass
$obj = (object) ['toto' => (object) ['foo' => (object) ['bar' => (object) ['baz' => 'cool']]]];
// Full fledge class
class Toto
{
private $foo;
private $forbidden;
public function __construct()
{
$this->foo = (object) ['toto' => (object) ['foo' => (object) ['bar' => (object) ['baz' => 'cool']]]];
$this->forbidden = (object) ['toto' => (object) ['foo' => (object) ['bar' => (object) ['baz' => 'cool']]]];
}
public function __get($name)
{
if (property_exists($this, $name) && 'forbidden' !== $name) {
return $this->$name;
}
}
}
echo '<pre>', PHP_EOL;
assert(property_exists_recursive($obj, 'toto->foo->bar->baz'));
assert(property_exists_recursive($obj, 'toto->foo->toto->baz'), 'the toto property does not exists');
assert(property_exists_recursive(new Toto, 'foo->toto->foo'));
assert(property_exists_recursive(new Toto, 'forbidden->toto->foo'), 'the private $forbidden property is not accessible');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment