Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between old-style and new-style PHP constructors

Tags:

oop

php

php4

Could someone tell me how the "old-style" object constructor is different from the "new-style" constructor? I'm learning PHP OOP, and I want to know when I'm reading old syntax vs new syntax, and better understand how OOP has changed in PHP over time.

New Style

class aObject
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}
like image 781
White Lotus Avatar asked Jan 02 '16 12:01

White Lotus


1 Answers

The "old" constructor syntax is referring to PHP4. The last release of PHP4 was in 2008, and the first release of PHP5 was in 2004. This is an example of an old-style class and a new-style class.

Old (PHP4)

<?php

class MyOldClass
{
    var $foo;

    function MyOldClass($foo)
    {
        $this->foo = $foo;
    }

    function notAConstructor()
    {
        /* ... */
    }
}

New (PHP5+)

<?php

class MyNewClass
{
    var $foo;

    public function __construct($foo)
    {
        $this->foo = $foo;
    }

    public function notAConstructor()
    {
        /* ... */
    }
}

You'll notice a couple of things here. The most significant change is that the canonical way to name a constructor has changed from ClassName() to __construct(). This gives all class constructors the same, predictable name--a necessary convenience. Imagine you had a class called ParentClass with 20 children, each with their own constructors. If you wanted to call the parent constructor from each child class, you'd call ParentClass::ParentClass(). If you wanted to change the name of ParentClass, you'd have to change all 20 constructor calls. But, with the new method, you'd just call parent::__construct(), which would always work, even when the parent class's name changes.

Related to this change, PHP5 also introduced class destructors (__destruct()), which is called when an object is destroyed (the opposite of a constructor).

Another key change is that PHP5 introduced method and property visibility which allows a sort of "access control" for methods and properties of the class. Only methods and properties marked public cam be accessed from contexts outside of the class or its children. Here are examples of this:

<?php

class StackOverflow
{
    /* This can be accessed from anywhere.
     *
     * You can access it from outside the class:
     *     $so = new StackOverflow();
     *     $so->publicProperty = 10;
     *     echo $so->publicProperty;
     * 
     * Or from inside the class:
     *     $this->publicProperty = 5;
     *     echo $this->publicProperty;
     */
    public $publicProperty = 1;

    /* This can be accessed only from methods inside this class.
     *
     *     $this->privateProperty = 5;
     *     echo $this->privateProperty;
     * 
     * You cannot access it from outside the class, as above.
     * Private properties cannot be accessed from child classes,
     * either.
     */
    private $privateProperty = 2;

    /* This can be accessed only from methods inside this class,
     * OR a child-class.
     *
     *     $this->protectedProperty = 5;
     *     echo $this->protectedProperty;
     * 
     * You cannot access it from outside the class, as with public.
     * You can, however, access it from a child class. 
     */
    protected $protectedProperty = 3;
}

Now, methods work the exact same way. You can mark a function (method) within a class as public, private, or protected. In PHP4, all class members were implicitly public. Similarly, a constructor (__construct()), can also be public, private, or protected!

If a class does not contain a public constructor, it cannot be instantiated by code outside of the class (or, its children, for protected). So how would you use such a class? Well, static methods, of course:

<?php

class ClassWithPrivateConstructor
{
    private $foo;

    private function __construct($foo)
    {
        $this->foo = $foo;
    }

    public static function fromBar($bar)
    {
        $foo = do_something_to($bar);

        return new self($foo);
    }
}

To instantiate this class from somewhere else, you'd call:

$obj = ClassWithPrivateConstructor::fromBar($bar);

This can be useful when you need to pre-process input before calling the constructor, or when you need multiple constructors that take different parameters.

This method names, __construct(), and other method names that begin with __, like __get(), __set(), __call(), __isset(), __unset(), __toString(), etc. are called magic methods.

PHP5 brought a lot of dramatic changes, but largely tried to maintain compatibility with PHP4 code, and thus, old-style constructors were still allowed.

PHP7 has now been released this year, with no changes to constructor syntax. The only significant class-related change in PHP7 was to allow the use of Anonymous Classes (see here).

As of PHP7, the old-style constructors are officially deprecated (raises E_DEPRECATED error), and will be removed entirely in PHP8.

like image 158
Will Avatar answered Oct 05 '22 02:10

Will