0

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 ?

kxc
  • 1,357
  • 2
  • 16
  • 39
  • 2
    Note that the new properties defined in the actual code will always be `public`.... if you want `protected` or `private` you need to define them explicitly in your class definition – Mark Baker Sep 08 '14 at 08:23
  • also, you should always code with `error_reporting(E_STRICT | E_NOTICE)` – Joshua Sep 08 '14 at 08:36

2 Answers2

2

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.

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • The explanation is plain wrong. In OP's example `Foo` does obviously not implement `__set()`. PHP allows to declare and initialize `public` class members on the fly – hek2mgl Sep 08 '14 at 08:45
  • @hek2mgl: You clearly didn't read my answer thoroughly. I explain that object overloading is available, but I consider it to be bad, for reasons mentioned both in the link, and further down the answer. I then procede to give an example of a class where overloading wouldn't work: implementing a `__set` that throws an excpetion would cause the OP's code to fail – Elias Van Ootegem Sep 08 '14 at 08:50
  • Again, this question is not about `overloading`. Please read the question (and probably other answers) again – hek2mgl Sep 08 '14 at 08:52
  • @hek2mgl: This question ***is*** about overloading: [PHP's definition of overloading](http://php.net/manual/en/language.oop5.overloading.php) is _"[..] means to dynamically "create" properties and methods"_. It's a silly term, and a bad idea [as I've often stated before](http://stackoverflow.com/questions/25702163/creating-anonymous-objects-in-php-which-extends-something/25709164#25709164), but that's what it's called... so sit-rap: adding properties on the fly is called overloading, It does not require a `__set` method, it's a silly term, and a bad idea we're on the same page here – Elias Van Ootegem Sep 08 '14 at 08:54
  • @hek2mgl: Yes, I have. What's your point? We're on the same page. But really, you seem to be hell-bound on disagreeing with me... not sure why, but heck: whatever works – Elias Van Ootegem Sep 08 '14 at 08:57
  • Please don't take it personal, but we are not at the same page here. And this is my point. You are talking about `overloading` and I talk about implicit property declaration. These are two different things. – hek2mgl Sep 08 '14 at 09:21
  • @hek2mgl: You haven't read the manual, then. PHP calls implicit property declaration _"object overloading"_ I linked to the official PHP docs. Here's the same link again: [Overloading](http://php.net/manual/en/language.oop5.overloading.php) that is _exactly_ what we're all talking about. Like I said before, and will keep on repeating: I'm not happy about the terminology either, but implicit property declaration is called overloading in the PHP lingo. Not my choice, but it is what it is – Elias Van Ootegem Sep 08 '14 at 09:28
1

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.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266