[PHP] Modification d'une propriété privée de classe à l'exécution
Publié le 03/12/2019 • Actualisé le 03/02/2020
Dans ce bout de code, nous allons voir comment modifier une propriété privée d'un objet PHP. J'ai récemment eu un cas d'utilisation concret quand j'ai du créer ma configuration pour le bundle EasyDeploy. J'ai eu à modifier une propriété privée de l'objet DefaultConfiguration
pour que le déploiement puisse fonctionner.
[Maj du 03/02/2020] Ajout de tests unitaires et amélioré l'affichage des résultats.
<?php
declare(strict_types=1);
namespace App\Controller\Snippet;
use Symfony\Component\HttpFoundation\Request;
/**
* J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
* Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
* ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
* Les services sont injectés dans le constructeur du contrôleur principal.
*/
trait Snippet61Trait
{
public function snippet61(Request $request): void
{
$class = \get_class($request);
echo \sprintf('> Request value object class: %s'.PHP_EOL, $class);
// This code "$request->isHostValid" would provoke a PHP error as the "isHostValid"
// is private (check out the unit tests)
$property = (new \ReflectionClass($request))->getProperty('isHostValid');
$property->setAccessible(true); // now we can read and write "isHostValid"
echo '> isHostValid: '.((bool) $property->getValue($request) ? 'true' : 'false').PHP_EOL;
$property->setValue($request, false);
echo '> isHostValid: '.((bool) $property->getValue($request) ? 'true' : 'false');
// That's it! 😁
}
}
Exécuter le snippet ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫ Plus sur Stackoverflow Lire la doc Snippet aléatoire
<?php
declare(strict_types=1);
namespace App\Tests\Integration\Controller\Snippets;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\Request;
/**
* @see Snippet74Trait
*/
final class Snippet61Test extends KernelTestCase
{
/**
* @see Snippet61Trait::snippet61
*/
public function testSnippet61(): void
{
$request = Request::create('/en/snippets/modifying-a-private-class-property-at-runtime');
$property = (new \ReflectionClass($request))->getProperty('isHostValid');
// As of PHP 8.1, private properties are accessible with reflection!
// @see https://phpbackend.com/blog/post/php-8-1-accessing-private-protected-properties-methods-via-reflection-api-is-now-allowed-without-calling-setAccessible
if (PHP_VERSION_ID < 80100) {
try {
self::assertNull($property->getValue($request));
self::fail('A ReflectionException should be raised!');
} /* @noinspection PhpRedundantCatchClauseInspection */
catch (\ReflectionException) {
}
}
$property->setAccessible(true);
self::assertTrue($property->getValue($request));
$property->setValue($request, false);
self::assertFalse($property->getValue($request));
}
}