This concept is adapted from C++. A 'friend' class can access the 'protected' members of the class in which it is declared as a friend.
Unfortunately, there is no clean, easy-to-use and fast solution for this yet, and a lot of projects have asked for such a feature for years. Today, the only alternatives are :
- Use Reflection or Closure::bind() to bypass every access protection. It does the job, but it is an ugly hack, breaking every OOP principles. We're talking about access control here, more than a hack to access anything from anywhere,
- Rely on a big warning in the documentation. Some, like symfony, also add an '@internal' tag in their phpdoc block. This can be checked in an IDE but that's nothing more than information, not access restriction.
- Guilherme Blanco proposed a mechanism to restrict class extension, that some consider as a way to enforce access control. As a class could be extended from the same namespace only, it would be a way to restrict access to protected members. But it implies that you must extend a class to access its protected members, which is very different from the 'friend class' concept.
The subject was discussed years ago, and it was decided not to implement 'friend class' declarations (see https://bugs.php.net/bug.php?id=34044). But the discussions occurred ten years ago when the PHP 5 OO system was young. The context is very different now.
It would be globally similar to C++ friend classes, except that a PHP friend class would have access to protected resources, but not private ones ('private' would remain private).
The inheritance rules would be similar to C++ rules (adapted as C++ friend classes access private resources) :
- Friendships are not symmetric – If class A is a friend of class B, class B is not automatically a friend of class A.
- Friendships are not transitive – If class A is a friend of class B, and class B is a friend of class C, class A is not automatically a friend of class C.
- Friendships are not inherited – A friend of class Base is not automatically a friend of class Derived and vice versa; equally if Base is a friend of another class, Derived is not automatically a friend and vice versa. (Can be discussed, alternative : 'friend Base' allows access from Base only, 'friend Base*' allows access from Base and derived classes, maybe also a syntax to declare friends using namespaces).
- Access due to friendship is inherited – A friend of Derived can access the protected members of Derived that were inherited from Base (simpler than the C++ rule as friend classes and derived classes have the same access rights).