16 votes

PHP autoload et variable statique dans une fonction

\=== Base.php ===

<?php
class Base
{
    public static function e()
    {
        static $number = 0;
        $number++;
        var_dump($number);
    }
}

\=== A.php ===

<?php
class A extends Base {}

\=== B.php ===

<?php
class B extends Base {}

\=== test.php ===

function __autoload($classname)
{
    require_once("{$classname}.php");
}

Base::e();
A::e();
B::e();

php test.php, le résultat est :

int(1)
int(2)
int(2)

Pourquoi le résultat n'est pas 1,1,1 ?

6voto

bwoebi Points 12576

Essayez

require "Base.php";
Base::e();
require "A.php";
A::e();

vs.

require "Base.php";
require "A.php";
Base::e();
A::e();

Le premier donne lieu à int(1) int(2) tandis que la dernière donne int(1) int(1) .

Pourquoi ?

Lorsqu'une classe est liée, le static le contenu variable est copié à ce moment précis, tel qu'il est actuellement. Il n'y a pas de sauvegarde de la valeur originale de la variable statique.

Cela implique que, lorsque la variable statique est 0 quand la classe A est lié, A::e() aura 0 comme valeur statique ; dans le cas où il s'agit de 1 , A::e() aura également 1 comme valeur.

Similaire pour B::e() alors, comme Base::e() y A::e() sont indépendants car les valeurs sont copiées (pas de références). Il aura également la même variable statique Base::e() a au moment de la liaison de B .

1voto

Robert Points 6284

J'ai fait quelques recherches sur ce problème et c'est vraiment bizarre.

Les propriétés statiques à l'intérieur des méthodes conservent leur état entre les instances de l'objet. Ce qui peut prêter à confusion. Il y a aussi deux statiques : l'une est la fonction statique et l'autre est la variable statique à l'intérieur de la méthode.

C'est peut-être lié à l'autochargeur. J'ai fait un exemple similaire au vôtre mais sans utiliser de méthodes statiques mais en utilisant une variable statique dans la méthode. Le résultat est 1:1:1 en utilisant l'autoloader et le même fichier.

<?php
class Base
{
    public function t()
    {
        static $number = 0;
        $number++;
        var_dump($number);
    }

    public static function e()
    {
        static $number = 0;
        $number++;
        var_dump($number);
    }
}

$base = new Base();
$base->t();

$a = new A();
$a->t();

$b = new B();
$b->t();

Aussi, si vous n'exécutez pas Base::e() le résultat est correct.

J'ai fait require_once sans autoloading et ça marche toujours. C'est donc bien à cause de l'autoloader.

Si vous mettez

require_once "Base.php";
require_once "A.php";
require_once "B.php";

au lieu de la fonction autoloader, cela fonctionne. Je n'en ai aucune idée. J'ai essayé de trouver quelque chose en considérant les variables statiques avec l'autoloader mais sans succès. Cependant, cette réponse peut vous donner un indice.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X