PHP object returns false if there are no properties
I am trying to create a class that will contain a set of properties. it will be used like this:
$class = new test_class();
$class->property;
$class->second_property;
Basically, if properties exist, then they are true; if properties do not exist, they are false. Properties don't matter, only existence.
Now I want to do something like this:
$class = new test_class();
var_dump($class->property); // false - property does not exist
var_dump($class->second_property); // true - second_property exists
var_dump( (bool) $class); // true
So, if even one property of the test class exists, var dumping $class
will show true because it's an object.
However, in a situation where the class has no properties, I want this to happen:
$class = new test_class();
var_dump($class->property); // false - property does not exist
var_dump($class->second_property); // false - second_property does not exist
var_dump( (bool) $class); // false
But I still want it to $class
be instanceof
test_class
, but return false in a boolean test.
Is it possible? If so, how do I do it?
Thanks, Ozzy
change
To clarify, I'm already using the magic function __get (). I want this to happen, if test_class
does not have the properties, when it is executed var_dump
, it returns false, and instanceof
returns test_class
.
development ...
I am creating a complex permission system. The user gets assigned sections and each section has a set of permissions.
It will work like this:
$user = permissions::get_user(USER_ID_HERE);
// Every property of the $user is a section
var_dump($user->this_section_exists); // true - returns an object
var_dump($user->this_section_doesnt); // false - returns a boolean
If the section exists, it returns a section permissions object.
var_dump($user->this_section_exists); // true
var_dump($user->this_section_exists->this_permission_exists); // true
var_dump($user->this_section_exists->this_permission_doesnt); // false
Here's an example of an edge:
var_dump($user->this_section_doesnt); // false
var_dump($user->this_section_doesnt->some_permission);
// This should also return false, which it does,
// But it throws a notice: "Trying to get property of non-object"
I want to be able to either suppress this notification without making any changes to the code that calls the class, i.e. no @ to suppress .. or be able to return an object without any properties that evaluates to false on a boolean test,
What I want to do is if test_class has no properties, then when var_dump is executed on it it returns false and instanceof will return test_class.
This is not possible, var_dump
will always show you the correct type for what it was created for.
No, you cannot do it exactly the way you wrote it. But you can emulate something like this:
class A {
public function __toString() { // this is what you want, but it only works when you use your object as a string, not as a bool.
if (count(get_class_vars(__CLASS__))) { // so if the class has at least 1 attribute, it will return 1.
return '1';
} else {
return '0';
}
}
}
$a = new A;
var_dump((bool)(string)$a); // false
If I add a property to class A, it returns true. You can also use it without (bool)
.
if ((string)$a) {
echo 'I am not empty';
} else {
echo 'I am an empty object';
}
If you don't want to use (string)
, you have one option to create a method containing the code from __toString()
and call it instead of casting.
Literature:
- __ toString ()
- get_class_vars ()
-
__CLASS__
PS: About what you said - do var_dump()
on the object to return false. No, It is Immpossible.
You can try PHP magic function
<?php
class Test {
private $name = 'name';
public $age = 20;
public function __get($name) {
return isset($this->$name) ? true : false;
}
public function __toString() {
return true;
}
}
$object = new Test();
var_dump($object->name); // output `true`
var_dump($object->age); // output `20`
var_dump($object->notfound); // output `false`
var_dump((bool)$object); // output `true`
You can do some packing with __ get () to manipulate the response.
Say something like
class test_class {
private $_validProperties;
public function __construct()
{
$this->validProperties = array('foo', 'bar', 'widget');
}
public function __get($prop)
{
if (isset($this->_validProperties[$prop])
{
return true;
}
return false;
}
}
$a = new test_class();
var_dump($a->foo); //true
var_dump($a->tree); //false
If I understand you correctly, I can do it.
Hope this helps you.
<?php
class Permissions {
private $userPermissions = array(
1 => array(
'Blog' => array('Post'),
),
);
private $permission;
public function __construct($id) {
$this->permission = $this->userPermissions[$id];
}
public function __get($name) {
if(isset($this->permission[$name])) {
return new $name($this->permission[$name]);
}
return new Notfound();
}
}
class Blog {
private $permission;
public function __construct($permission) {
$this->permission = $permission;
}
public function __get($name) {
if(($key = array_search($name, $this->permission)) !== false) {
return new $name();
}
return new Notfound();
}
public function __tostring() {
return true;
}
}
class Post {
public function __get($name) {
return isset($this->$name) ? true : new Notfound();
}
public function __tostring() {
return true;
}
}
class Notfound {
public function __get($name) {
return false;
}
public function __tostring() {
return false;
}
}
$user = new Permissions(1);
var_dump('Blog ', $user->Blog); // return Blog
var_dump('Blog:Post', $user->Blog->Post); // return Post
var_dump('News', $user->News); // return Notfound
var_dump('News:Post', $user->News->Post); // return false