This rule raises an issue when reflection is used to change the visibility of a class, method or field, and when it is used to directly update a
field value. Altering or bypassing the accessibility of classes, methods, or fields violates the encapsulation principle and could lead to run-time
errors.
Noncompliant Code Example
class MyClass
{
public static $publicstatic = 'Static';
private static $privatestatic = 'private Static';
private $private = 'Private';
private const CONST_PRIVATE = 'Private CONST';
public $myfield = 42;
private function __construct() {}
private function privateMethod() {}
public function __set($property, $value) {}
public function __get($property) {}
}
$clazz = new ReflectionClass('MyClass');
$clazz->getstaticProperties(); // Noncompliant . This gives access to private static properties
$clazz->setStaticPropertyValue('publicstatic', '42'); // OK as there is no overloading to bypass and it respects access control.
$clazz->getStaticPropertyValue('publicstatic'); // OK as there is no overloading to bypass and it respects access control.
// The following calls can access private or protected constants.
$clazz->getConstant('CONST_PRIVATE'); // Noncompliant.
$clazz->getConstants(); // Noncompliant.
$clazz->getReflectionConstant('CONST_PRIVATE'); // Noncompliant.
$clazz->getReflectionConstants(); // Noncompliant.
$obj = $clazz->newInstanceWithoutConstructor(); // Noncompliant. Bypassing private constructor.
$constructor = $clazz->getConstructor();
$constructorClosure = $constructor->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$constructor->setAccessible(true); // Noncompliant. Bypassing constructor accessibility.
$prop = new ReflectionProperty('MyClass', 'private');
$prop->setAccessible(true); // Noncompliant. Change accessibility of a property.
$prop->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
$prop->getValue($obj); // Noncompliant. Bypass of the __get method.
$prop2 = $clazz->getProperties()[2];
$prop2->setAccessible(true); // Noncompliant. Change accessibility of a property.
$prop2->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
$prop2->getValue($obj); // Noncompliant. Bypass of the __get method.
$meth = new ReflectionMethod('MyClass', 'privateMethod');
$clos = $meth->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$meth->setAccessible(true); // Noncompliant. Change accessibility of a method.
$meth2 = $clazz->getMethods()[0];
$clos2 = $meth2->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$meth2->setAccessible(true); // Noncompliant. Change accessibility of a method.
// Using a ReflectionObject instead of the class
$objr = new ReflectionObject($obj);
$objr->newInstanceWithoutConstructor(); // Noncompliant. Bypassing private constructor.
$objr->getStaticPropertyValue("publicstatic"); // OK as there is no overloading to bypass and it respects access control.
$objr->setStaticPropertyValue("publicstatic", "newValue"); // OK as there is no overloading to bypass and it respects access control.
$objr->getStaticProperties(); // Noncompliant. This gives access to private static properties
// The following calls can access private or protected constants.
$objr->getConstant('CONST_PRIVATE'); // Noncompliant.
$objr->getConstants(); // Noncompliant.
$objr->getReflectionConstant('CONST_PRIVATE'); // Noncompliant.
$objr->getReflectionConstants(); // Noncompliant.
$constructor = $objr->getConstructor();
$constructorClosure = $constructor->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$constructor->setAccessible(true); // Noncompliant. Bypassing constructor accessibility.
$prop3 = $objr->getProperty('private');
$prop3->setAccessible(true); // Noncompliant. Change accessibility of a property.
$prop3->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
$prop3->getValue($obj); // Noncompliant. Bypass of the __get method.
$prop4 = $objr->getProperties()[2];
$prop4->setAccessible(true); // Noncompliant. Change accessibility of a property.
$prop4->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
$prop4->getValue($obj); // Noncompliant. Bypass of the __get method.
$meth3 = $objr->getMethod('privateMethod');
$clos3 = $meth3->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$meth3->setAccessible(true); // Noncompliant. Change accessibility of a method.
$meth4 = $objr->getMethods()[0];
$clos4 = $meth4->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
$meth4->setAccessible(true); // Noncompliant. Change accessibility of a method.