Make everything private in your PHP classes

It is a good recommendation to make everything private in a class : constants, methods, properties. With private, comes a tighter control on the element : no one from outside may use it, limiting the unwanted impact on the object. Of course, some of the class has to be accessible from the outside, or the object may only be manipulated as a token.

PHP has three levels of visibility : private, protected and public. They are applicable to properties, methods and constants. Constant may be declared private since PHP 7.1. Before that, they were always public, just like properties or methods when they are not configured explicitly otherwise.

Public by default makes coding a lot easier : as long as the object is available, it is possible to look into it, check or adapt values, call any method to make its running. While developing, especially when conception is weak, this prevents frustrating situations where data is available, but hidden somewhere in a class, or by a bug.

Eventually, when the code matures, it becomes desirable to apply the above principle of encapsulation. This helps keeps the code clean and made of independent components. This is the beginning of a long hunt.

Protected methods may be used anywhere in inheriting classes. Sometimes, those are a few, and sometimes, not. Public properties are suddenly a nightmare to hunt : they may be used anywhere in a few million lines of code.

Exakat visibility report

This is were the Exakat visibility report helps. It actually keeps track of all usage of constants, properties and methods, and provides an overview for each of them. The visibility report is available in the ‘Audit logs’ section of the Ambassador report.

Constants

Class constants are the one that will yield the most results : since the feature is very recent, very little PHP code is taking advantage of them. Most of them are still ‘none’, which is public. The green stars means here that the constant is not marked, and that it is the best visibility : this constant is also used in ‘public’ situations. Making the visibility protected or private will break the code.

Methods

Methods are reported, with also some colorful stars : green is still the best possible choice. The sellers() method could be a ‘protected’ method, although it is currently declared ‘public’. No star in the private column means that this option is not possible : the method was used by a child class. Thus, upgrading the visibility to protected makes the code better, and still working.

The static run() function is currently lacking the visibility, and may be also upgraded to protected.

Properties

Properties are presented just like constants and methods : green is the best available, and red/orange colors are used if it is not the best choice available. Here, $sellers (the property) may be upgraded to private, as it seems that no other class is making a direct use of it : given the previous observation, it seems that other classes uses sellers() (the method) to access it. This would be a classic example of visibility being enforced in the code, but not explicitly specified.

Properties default value

Properties have a ‘value’ column, which mentions the current default value. It is recommended to always set a default value. Even ‘null’ helps the reader to understand that this property should be initialized at some point in the code. Here, $gateway is probably a communication device, and an object.

Properties may be a constant

Finally, the last column is also a possible upgrade for the property. It mentions properties that are never written, and only used for reading. They may be set at class definition time, and then, never altered ever again.

<?php
Class foo{
   private $tmpDir = '/tmp/private';

   function log($message) {
    // $tmpDir is read but not modified.
    $fp = fopen($this→tmpDir.'/mylog.log', 'a');
    fwrite($fp, $message.PHP_EOL) ;
    fclose($fp) ;
   }
}
?>

Such situations happens in a few situations :

  • The property holds an array, and arrays were only allowed in constants since PHP 5.4. This is basically a traditional habit that may be modernized.
  • This property was dynamic initially, but finally regressed to a literal as the code matured.
  • The property is used in a string (“$this->tmpDir/mylog.log”), where a constant is not convenient.
  • The first choice when building a class is a property, not a constant.

In any case, constant may be a choice to consider here. Properties that are never modified are actually constant, so it is advised to make them appear as such. That will prevent future pains, when the property is actually modified inadvertently.

Update your code with your brain

The visibility report is a great to help applying sensible coding standards. It is build on the existing code, and may be reporting extreme closings with a few situations.

  • Some part of the code uses dynamic access to that class, and this is not reported.
  • The code is a library. It will be used inside other repositories’ code, and this explain why so many methods are ‘unused’. Think carefully before raising visibility.
  • The code is being upgraded and some properties are already public for the upcoming upgrade. This is actually a valid excuse, as future evolutions are not visible in the code, or they would be the code. This is also an evergreen pretext : it applies to every line of code past, present and future.

Conclusion

The visibility report offers a nice overview of classes and their visibility configuration. It is very efficient to spot overlooked situations that benefit from raised visibility : less unexpected impact on the current class, more decoupled code and atomic components.
Sometimes, it also raises questions. For example, when a property is not suggested for a raise to ‘private’, while it is supposed to be only used by the class. This means that some leftover code is already making use of it in a public or protected way. It is now worth investigating even further.