📜 ⬆️ ⬇️

Private classes. Hiding in php

In php, as in most other OOP languages, there are visibility modifiers. These are the keywords public, protected and private. But they apply exclusively to properties, methods, or constants. These modifiers are closely related to the ability to encapsulate data. It is worth noting that in languages ​​such as java, C #, go ( https://golang.org/doc/go1.4#internalpackages ), ruby ​​( https://habr.com/post/419969/ ), crystal ( https : //crystal-lang.org/reference/syntax_and_semantics/visibility.html ) it is possible to limit the scope of packages (packages) or classes \ types. In php there is no possibility to limit the scope for classes - any connected class is accessible from any other class. However, you can emulate this feature using several tricks.


For which you may need to hide at the class level:



Separately, you can select the partition of the "large" classes into small objects. It is considered good practice to limit the complexity (and the number of lines) of both individual methods and classes. The number of lines here goes as one of the markers, that the class method or the class itself takes on unnecessary responsibility. When refactoring a public method, we move parts of it to private \ protected methods. But when, for one reason or another, a class grows and we separate a separate entity from it, these most private \ protected classes are transferred to a separate class, thus we indirectly open access to methods that were previously limited to the scope of one class.


Now, the actual methods of emulation of concealment.


At the level of agreement code design


Using PHPDoc comments, you can mark a class, trait, or interface as internal ( http://docs.phpdoc.org/references/phpdoc/tags/internal.html ). However, some IDE (for example PhpStorm) can understand such tags.


Use runtime information


During execution of the code, you can check where the class constructor was called from. For example, through the debug_backtrace method ( http://php.net/manual/ru/function.debug-backtrace.php ) or use the same Xdebug functionality to control the code in the dev \ test environment. An example of a framed solution is here ( https://coderwall.com/p/ixvnga/how-emulates-private-class-concept-in-php ).


use debug_backtrace
 /** * The private class */ final class PrivateClass { /** * defines the only class able to instantiate the current one * * @var string */ private $allowedConsumer = 'AllowedPrivateClassConsumer'; /** * constructor * * @throws Exception */ public function __construct() { /** * here comes the privacy filter, it could be extracted to a private method * or to a static method of another class with few adjustments */ $builder = debug_backtrace(); if (count($builder) < 2 || !isset($builder[1]['class']) || $builder[1]['class'] !== $this->allowedConsumer) { throw new Exception('Need to be instantiated by '.$this->allowedConsumer); } } } 

Use anonymous classes


Relatively new features in php are anonymous classes ( http://php.net/manual/ru/language.oop5.anonymous.php ). By describing an anonymous class inside a protected method, we seek to hide it. In order not to enclose the class definition inside a function, you can describe the "private" class in a separate file as abstract, and already expand it in the definition of an anonymous class. A good example of using this method is at this link ( https://markbakeruk.net/2018/06/25/using-php-anonymous-classes-as-package-private-classes/ ).


Based on the material found, it is clear that the class-hiding functionality is to some extent in demand (and exists in many languages), but the practice of its use is very limited, possibly lacking a description of examples in various "best practices", template collections and similar sources. Which in my opinion is rather strange, that there is an emphasis on hiding the internal methods and properties of objects, but almost no one pays attention that larger logical pieces of code in the form of utility classes of libraries or domain domains remain in the global visibility space.


')

Source: https://habr.com/ru/post/435894/


All Articles