75

Is there any advantage to using __construct() instead of the class's name for a constructor in PHP?

Example (__construct):

class Foo {
    function __construct(){
        //do stuff
    }
}

Example (named):

class Foo {
    function Foo(){
        //do stuff
    }
}

Having the __construct method (first example) is possible since PHP 5.


Moderator note: The question relates to functionality that was available in PHP 5. Since PHP 7.0, named constructors have been deprecated and removed in PHP 8.0.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Newtang
  • 6,414
  • 10
  • 49
  • 70

10 Answers10

73

The advantage is that you don't have to rename it if you rename your class. DRY.

Similarly, if you have a child class, you can call the parent constructor:

parent::__construct()

If further down the track you change the class the child class inherits from, you don't have to change the construct call to the parent.

It seems like a small thing, but missing changing the constructor call name to your parents' classes could create subtle (and not so subtle) bugs.

For example, if you inserted a class into your hierarchy, but forgot to change the constructor calls, you could start calling constructors of grandparents instead of parents. This could often cause undesirable results which might be difficult to notice.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Bazman
  • 1,230
  • 9
  • 10
  • 6
    The edits to this answer are being discussed on meta: [What are the edit policy today for questions about obsolete functionality?](https://meta.stackoverflow.com/q/426013/1839439) – Dharman Aug 13 '23 at 13:17
20

__construct was introduced in PHP5. It is the way you are supposed to do it now. I am not aware of any advantages per se, though.

From the PHP manual:

For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics

If you're on PHP5 I would recommend using __construct to avoid making PHP look elsewhere.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
16

The reasoning in the accepted answer is wrong.

I find renaming classes to be a bad practice: things can get tangled when using Reflection or complex dependence structure like PHP frameworks often do. It also break dependencies regardless of the constructor syntax. As a rule of thumb:

  • if the class name conflicts, use namespaces
  • if the class name sucks, use Decorator pattern or inheritance
  • if the class has to be adapted to the project, use Adapter pattern

Java, C++ or C# don't use __construct, they use named constructor and there's no issue with them. PHP is, however, a different story:

1. PHP 5.3.3 removed named constructors in namespaces

2. PHP 7.0 deprecated all named constructors

3. PHP 8.0 removed all named constructors

So named constructors are no longer an option. But to answer your question: the reason for the deprecation/removal named constructors is probably that PHP functions/methods are case insensitive, so in legacy PHP code there was this problem:

class Filter {
  function filter() {
    echo "this is a constructor, not a method!";
  }
}

// so you could never write
// $filter = new Filter;
// $filter->filter();

This is the official PHP RFC reasoning behind the removal of named constructors.


Funnily, PHP variables are case sensitive, there's little reasoning in PHP development, see this funny legacy official PHP 4.0 release announcement.

Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
  • 2
    can you please rewrite paragraph #2 for clarity? (one starting with "Renaming ...". I am lost on why it is a bad practice to rename classes, and why there are no issues with Java, C, C++, and how it is relevant to this question. Does it mean PHP also should use named constructor as Java, C, C++ or are there issues? What are the issues? – Dennis Apr 24 '14 at 13:33
  • 1
    @Dennis See my updated answer. It is relevant to the accepted answer, because Bazman gave wrong point about renaming the class: he didn't have the point about the namespaces in his answer by the time I provided my answer, he copied it from my answer later. Now he takes the credit, but never mind, it doesn't affect the information itself and nobody cares. – Jan Turoň Apr 25 '14 at 11:56
  • Agreed. Moreover, renaming/refactoring a class name is IDEs job. Not to mention how ugly that name is, with 2 underscores :-( Since the name is unique in a class, they could have chosen a single `_` or a new, better "unique" sounding keyword. – Déjà vu Aug 13 '23 at 02:51
  • @Déjàvu the double underscore is how every other magic method is already named within PHP, using a single underscore would have been abysmally confusing. – Félix Adriyel Gagnon-Grenier Aug 15 '23 at 15:13
  • I really try to keep an open mind, but I have no clue what "Renaming classes is a bad practice" is supposed to mean. Like what, if someone named a class `AwesomeController` ten years ago you'd keep it that way by fear or renaming it? It makes not the smallest amount of sense to me. IDEs that allow for safe refactoring actions have existed for decades, if your codebase makes it unsafe to rename classes that's on you, not on the language or anything. – Félix Adriyel Gagnon-Grenier Aug 15 '23 at 15:15
  • 1
    @FélixAdriyelGagnon-Grenier In this case, I'd "rename" `AwesomeController` by Decorator or inherited class. There are usually public repos and package management that does scripted autoupdates. The packages have also dependencies and changes by hand break it. I admit it is not always the case (some projects don't have external dependencies or have Facade), so I rephrased the answer to sound more like my point of view rather than a strict general rule. – Jan Turoň Aug 15 '23 at 19:38
16

The main advantage I see for __construct, is that you don't have to rename your constructor if you change your class name.

gizmo
  • 11,819
  • 6
  • 44
  • 61
10

The best advantage of using __contruct() instead of ClassName() is when extending classes. It is much easier to call parent::__construct() instead of parent::ClassName(), as it is reusable among classes and the parent can be changed easily.

Ryan McCue
  • 1,628
  • 14
  • 23
10

In your example Foo::Foo is sometimes called a PHP 4 or old-style constructor because it comes from the days of PHP 4:

class Foo {
    // PHP 4 constructor
    function Foo(){
        //do stuff
    }
}

PHP 4 constructors will be deprecated but not removed in PHP 7. They will be no longer be considered as constructors in any situation in PHP 8. Future compatibility is definitely a big reason to not use this feature.

Levi Morrison
  • 19,116
  • 7
  • 65
  • 85
5

In PHP 7, the option to create the constructor as a function with the same name as the class will be removed. If you still do it, you will get a E_DEPRECATED.

You can read more about this proposal (the proposal is accepted) here: https://wiki.php.net/rfc/remove_php4_constructors

And a quote from there:

PHP 7 will emit E_DEPRECATED whenever a PHP 4 constructor is defined. When the method name matches the class name, the class is not in a namespace, and a PHP 5 constructor (__construct) is not present then an E_DEPRECATED will be emitted. PHP 8 will stop emitting E_DEPRECATED and the methods will not be recognized as constructors.

Also, you won't get a E_STRICT in PHP 7 if you define a method with the same name as the class AND a __construct().

You can see this also here:

PHP 7 will also stop emitting E_STRICT when a method with the same name as the class is present as well as __construct.

So I would recommend you to use __construct(), since you will have less issues with this in the future.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Rizier123
  • 58,877
  • 16
  • 101
  • 156
2

In PHP 5 the advantage would be that performance would be better. It will look for a constructor by the name of __construct first and if it doesn't find that, it will look for constructors by the name of className. So if it finds a constructor by the name __construct it does not need to search for a constructor by the name className.

Steven Oxley
  • 6,563
  • 6
  • 43
  • 55
2

Forward compatibility. There's always a chance that legacy code that's left in the language for backwards compatibility's sake will be removed in a future version.

Jeremy Privett
  • 4,455
  • 2
  • 32
  • 35
-2

I think that the main reason is that is the language convention. You don't need to force a language to act like someone else.

I mean, in Objective-C you prefix the constructors with -init, for example. You can make your own constructor using your class name but why? Are ther some reason to use this schema instead of the language convention?