Sugato Sengupta Sugato Sengupta - 4 months ago 11
PHP Question

undefined public member variables getting initialized?

I am surely going to get flamed for asking this but I need to clear my doubts. So, I don't mind getting some negative votes to begin with. I am in a paradox with the following code snippet and I am not sure what to call it.

I have defined a very simple class which has no public member variables yet. Now, in the constructor I am taking an array of values and initializing the members (which have not been defined yet) using a foreach loop like so:

error_reporting(E_ALL);
class Food{

function Food($construct){
foreach($construct as $key=>$value){
$this->$key = $value;
}

}


}
$food = new Food(array('name' => 'chicken' , 'unit' => 'kg' , 'calorie' => 10000));
var_dump($food);


I expected to see an error that the variables are not defined within the class, but to my surprise there wasn't any error! I dumped the object and I got the following output ( strange!)..

object(Food)[1]
public 'name' => string 'chicken' (length=7)
public 'unit' => string 'kg' (length=2)
public 'calorie' => int 10000


How is this even possible? Is it a safe practice f I do this? I want your pro opinion on this. Thanks a lot!

By the way, my wamp has php version => 5.3.13

I hope this question lives upto the community standards, because I am utterly confused.

Answer

This is possible in PHP and is the default implementation unless you have stated otherwise (via __get() and __set()). Creating public members on the fly is possible only for the current instance, it does not create it for the class overall. And it's possible from inside the class or from outside (e.g. via the instance).

$food->smth = 100;

will create public smth

An empty __set() magic method can prevent this behavior

public function __set($name, $value) { }

For the second question:

It is not safe and using public members at all is not safe (unless you have really good reason for exposing your properties). The convention says you have to have mostly private/protected members with accessors for them. So you can have the controll for the class from inside the class rather than from the instance of it. And for many other reasons, including code reusability.