Few days back I was asked to fire-fight an error, which is actually not a tough one but a bit troubling for a new developer. This error can be tagged as a ‘beginner level’ error but if you are not strong with your Object Oriented Programming concepts, even an experienced developer will be forced to struggle. The error that I am going to discuss today will be:
Fatal error: Call to private Vehicle::__construct() from invalid context in C:\Users\Project1X\TeamAlpha\VehicleClass.php on line 11
A stripped down version of the code which was throwing this error is given below:
private function __construct($part1,$part2)
echo "\n From Class Vehicle - part1 is $part1,part2 is $part2";
static public function showPartId($partId)
echo "\n Part Id is $partId";
$vehicleObj = new Vehicle('Windshield','Doors');
Any person writing object oriented PHP code should be clear with this fact that constructors are “functions” found in a class. They are automatically called when we create a new instance of a class using the keyword ‘new’. We should be aware that there are three levels of restriction for any member of a class, be it a variable or a function. These levels of restrictions are implemented using the keywords – private,public and protected. The definition for ‘private’ is that, the particular member can be accessed only from within the class. It is kind of a tradition that constructors in general are declared as ‘public’ though this is not a strict rule – constructors can also be declared as ‘private’ or even ‘protected’. Constructors in PHP can be either represented by the word ‘__construct()’ or by the name of the class itself. In the above example, even if you try to use the other way of calling a constructor, that is, by using the class name(in this case, private function Vehicle()),you will still get the same error because the visibility is ‘private’
Armed with the above knowledge, let us take a look at the error again. We can see that PHP is complaining that the call to the ‘private constructor’ is made from the wrong place. This is true because if we look at the code, we can see that the class is getting instantiated outside the ‘class code’, or the private constrctor is getting called from outside the class. You definitely cannot call a private member from outside the class. This error can be fixed either by making the constructor ‘public’ or by avoiding the
instantiation of the class outside the ‘class’. The decision whether to go this way or that way can be taken only if the person who is writing this code is fully aware of what he/she is trying to achieve using this code.
There are situations where, in order to prevent instantiation of the class from outside of the class, we make the constructor ‘private’. It is perfectly alright to make a constructor ‘private’ in such a situation because when a function/method (in our case the constructor) is declared as ‘private’ and when you try to instatiate that class from outside the class, PHP will throw an error thus preventing the instatiation of the class. This reinforces the concept that “a function/method which is declared as private cannot be called from outside the class because it is a private property of that particular class”. Also, there are situations like implementing a design pattern where we want to strictly control the class instatiation by making the class constructor as private or protected.
In the above code, if we remove the line of code where the class instantiation is done and then try to run the code using the line “Vehicle::showPartId(122);”, the code will give the desired output without any error. Some people may be wondering “how can this be true?”. The reason is that, when we use the scope resolution operator and try to access a class member, we are actually calling the ‘class function’ and not the function of any object. In fact, when we use the scope resolution operator, neither are we instantiating the class nor are we creating any object and hence the ‘private constructor’ does not come into play to create an error.
I hope that next time when you declare a class constructor, you will declare the level of restriction as ‘private’ or ‘public’ based on what you want to achieve using this class.
Till next time, Happy PHPing