kxc
kxc

Reputation: 1457

PHP Set variable in __construct()

Is it normal to not defined variable in class properties, but indicate at once in constructor ? I just learn OOP, and found that example:

class Foo {
  public function __construct($name) {
    $this->_name = $name;
  }
}

and it works, i can use this variable

$objFoo = new Foo('Fido');
echo $objFoo->_name; //output 'Fido'

But in class properties, there has no defined variable $_name, like public $_name in start of class. So if we dont define it directly, it will be created automatically throught constructor ? And is it real to set scope for variable that way, protected, private ?

Upvotes: 0

Views: 6130

Answers (2)

hek2mgl
hek2mgl

Reputation: 157947

Creating object members on the fly, meaning just assigning a value to it without declaring the member, is not limited to the constructor method. It can be done from inside of every method in the class or even from outside of the class, like this:

$c = new stdClass();
$c->foo = "bar";

While there are still a few use cases for this, I suggest to declare every class member explicitly in the head of the class. Also you will want in most cases to declare class members as protected or even private which requires an explicit declaration anyway.

Upvotes: 1

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76395

In PHP, this is called "object overloading", you can add/set new properties on (almost) any instance on the fly. However, you shouldn't do this. These properties make your code more error prone, less maintainable and overloaded properties that are added are slower: details here.

Pre-declaring properties allows for better documentation, your IDE's auto-completion function is actually worth something then, and you don't get in the habit of relying on something that doesn't always work. I tend to write my data models along these lines:

class DataModel
{
    /**
     * @var int
     */
    protected $id = null;

    /**
     * @var string
     */
    protected $name = null;

    /**
     * @var \DateTime
     */
    protected $birthday = null;

    public function __construct(array $data)
    {}//set values
    public function __set($name, $value)
    {
        throw new \BadMethodCallException('Do not attempt overloading, use getters and setter');
    }
}

I define getters and setters for all of the properties, to ensure type safety, and validation can be done. I expressly disable overloading because of the risk of typo's, and difficult debugging. I often find myself disabling __sleep, __serialize and all those magic methods for pretty much the same reason.

Upvotes: 2

Related Questions