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,
source to share
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:
PS: About what you said - do var_dump()
on the object to return false. No, It is Immpossible.
source to share
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`
source to share
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
source to share
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
source to share