Accéder à des attributs protégés depuis une méthode statique

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

20 juil. 2007, 13:00

Bonjour à tous,

Je reviens vous voir pour m'aider à comprendre le fonctionnement OO de PHP5.

Lors d'un de mes développements, j'ai découvert qu'en PHP, dans une méthode statique d'une classe, d'accéder aux attributs protégés d'une instance de cette classe.

Comme un petit exemple vaut mieux qu'un grand discours, voici un exemple illustrant mes propos :
<?php

error_reporting(E_ALL); // Pour être sûr de voir toutes les erreurs, même les E_STRICT

class Statut
{
	// *************
	// *** Attributs de la classe
	// *************
	protected $code;		// Ces attributs sont de visibilité "Protected"
	protected $message;
	
	
	
	// *************
	// *** Méthode de la classe
	// *************
	static public function get_db_statut()
	{	// Cette méthode est statique, donc pas d'instance de l'objet

		// Instanciation du nouvel objet statut
		$o_statut = new Statut();
		
		// Modification des attributs de visibilité "Protected" de l'instance de la classe, créé dans la méthode
		$o_statut->code 	= "Mon code";
		$o_statut->message 	= "Mon message" ;

		return $o_statut;
	}
}


echo "Appel de la méthode statique<br />";
$o_statut = Statut::get_db_statut();		// Aucune erreur affichée
print_r($o_statut);							// Les attributs de l'objet ont bien été affectés

echo "Modification d'un des attributs d'une instance de la classe<br />";
$o_statut = new Statut();
$o_statut->code 	= "Mon code";			// Modifications d'attributs de visibilité "protected"
$o_statut->message 	= "Mon message" ;		// Une erreur intervient
Or, je sais qu'en Java et en C++, ce n'est pas possible de faire ça ...
J'aimerais donc que l'on m'explique pourquoi PHP l'implémente :S
Modifié en dernier par zeus le 20 juil. 2007, 14:21, modifié 1 fois.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

20 juil. 2007, 13:45

Je pense que tu as eu quelques problèmes de recopiage parce que
$o_statut = Statut::get_db_statut();
...est null (get_db_statut() ne renvoit rien) et j'ai une erreur à l'avant-dernière ligne, comme on pouvait s'y attendre.

ViPHP
ViPHP | 928 Messages

20 juil. 2007, 13:46

Bonjour,
déjà vis à vis de l'error_reporting() E_STRICT n'est pas inclu dans E_ALL (il le devient à partir de PHP6). Donc pour bien voir toutes les erreurs :

Code : Tout sélectionner

error_reporting(E_ALL | E_STRICT)
(ce n'est pas le propos, mais c'était par rapport au commentaire dans ton fichier).

Ensuite à mon avis, PHP considère que les propriétés de tout objet déclaré dans un objet du même type sont accessibles. J'ai aussi fait le test avec une méthode non statique et PHP ne lache pas d'erreurs non plus apparament. Maintenant pourquoi ... peut être tout simplement parce que c'est la volonté de PHP d'agir comme ça ? Mais effectivement je ne trouve pas ça spécialement logique vis à vis de la protection des propriétés, d'autant plus que apparament ça marche aussi pour les private.

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 13:53

Salut :)

Si on peut déclarer des méthodes en statique, c'est pour nous permettre de ne pas instancier. Donc déclarer une méthode statique, pour instancier son objet est un peu bête :P

J'aurais plutôt vue ça comme ça :
<?php

header('content-type: text/plain');

class StatusA {

    protected static $code    = null;
    protected static $message = null;

    public static function get_db_status ( ) {

        self::$code    = 'Mon code';
        self::$message = 'Mon message';

        return array(
            self::$code,
            self::$message);
    }
}

$status = StatusA::get_db_status();
print_r($status);

// ou

class StatusB {

    public static $code    = null;
    public static $message = null;

    public static function get_db_status ( ) {

        self::$code    = 'Mon code';
        self::$message = 'Mon message';
    }
}

StatusB::get_db_status();
echo StatusB::$code     . "\n" .
     StatusB::$message  . "\n\n";

StatusB::$code    = 'Autre code';
StatusB::$message = 'Autre message';
echo StatusB::$code     . "\n" .
     StatusB::$message  . "\n";
Tu remarques les différents types pour les propriétés (public et protected).

Affichera donc :

Code : Tout sélectionner

Array ( [0] => Mon code [1] => Mon message ) Mon code Mon message Autre code Autre message
:)
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 19672 Messages

20 juil. 2007, 13:59

Donc déclarer une méthode statique, pour instancier son objet est un peu bête :P
Pas obligatoirement : c'est comme ça qu'on crée un singleton, on crée un constructeur privé et une méthode statique de récupération d'instance de classe.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

ViPHP
ViPHP | 928 Messages

20 juil. 2007, 14:04

Idem pour le design pattern factory : http://www.journaldunet.com/developpeur ... ry-2.shtml assez pratique d'ailleurs ;)

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 14:05

@Cyrano : Oui je suis au courant. Mais dans son cas c'est inutile, du moins, avec le code présenté.

Mais tu as raison de le souligner :)
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

20 juil. 2007, 14:20

@Hubert : Effectivement, j'ai essayé d'alléger au maximum et je suis allé trop loin :oops:
La méthode get_db_statut() retourne l'instance de Statut qu'elle a instanciée. Je corrige mon code d'origine. Désolé :?

@Genova : je ne savais pas, je prend note, merci

@HyWaN : Tu as un exemple très allégé de ce que fait cette méthode. Dans celle d'origine, il est très intéressant de ne pas instancier l'objet ;)
Cyrano et Genova sont très proche de ce que fait la classe.

En fait, ma question ne porte pas tellement sur "est-ce que c'est possible ?", puisque j'ai découvert que ça l'était, mais plutôt "Quel est l'utilité ?", surtout que c'est un comportement propre à PHP qui est impossible en C++ ou en Java :?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 14:29

Tu parles du singleton là ? :P
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 14:35

Le singleton est extrêmement pratique en fait.
Dans certain cas, ton objet ne doit être instancier qu'une seule et unique fois !

Par exemple, je travaille sur un MVC en ce moment. J'ai une classe qui se charge de dispatcher mes objets etc. Si mon objet est instancier plusieurs fois, on aura des soucis dans le dispatchage des objets. Donc on ne l'instancie qu'une seule et unique fois. Ca peut être utile aussi pour des connexions vers des tables etc.

Un petit exemple :
<?php

class Singleton {

    private static $_instance = null;

    private function __construct ( ) {

        // on lance les instructions qui n'ont besoin d'être faite qu'une
        // seule et unique fois !
    }

    public static function getInstance ( ) {

        if(null === self::$_instance)
            self::$_instance = new self();

        return self::$_instance;
    }
}

// on veut l'instance :
$singleton = Singleton::getInstance();
// on fait des opérations, des appels de méthodes etc.
// et si plus tard dans le code, on veut réavoir l'instance, on fait :
$singleton = Singleton::getInstance();

// l'objet ne sera pas recréé, mais l'instance sera retournée.
Edit : j'ai validé mon message sans faire exprès pour le précédent ... désolé.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

20 juil. 2007, 14:41

Si ce que tu cherches à me dire c'est que c'est ce comportement qui permet la création de singleton, quel est le principe équivalent en Java ou C++ ?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 14:46

Je ne connais ni Java ni C++ ^^ Enfin, j'ai un niveau scolaire.

Mais j'ai appris le design pattern dans un livre pour Java, donc ça doit exister. Attends je regarde dan mon livre ... En fait, la syntaxe est la même, et on apelle ça le design pattern Singleton, ou aussi un objet unique.
Le pattern Singleton garandit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance.
(chez O'Reilly)

Je ne vois pas ce que tu veux savoir de plus ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

20 juil. 2007, 14:51

J'ai mal compris ton code ...

Tu passes par un attribut statique, donc partager par toutes les instances de la classe, comme en Java et en C++.

Par contre, je ne vois pas l'intérêt de pouvoir accéder à un attribut non statique d'une instance de la classe dans une méthode statique de cette même classe.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 4674 Messages

20 juil. 2007, 15:00

Tes questions me font mal à la tête.

Déjà, tu as compris le code maintenant ? Il faut savoir ce qu'on cherche. J'ai l'impression qu'on ne cherche pas la même chose :?
Par contre, je ne vois pas l'intérêt de pouvoir accéder à un attribut non statique d'une instance de la classe dans une méthode statique de cette même classe.
Je tente de traduire.
Tu ne vois pas l'intérêt de faire $object->proprety dans une méthode statique de cette même classe. Donc $object, peut être $this (sauf certain cas). Hmm. Moi, j'y vois un intérêt, ce serait une récursivité dans les objets, avec les instances dans une propriété statique ou non statique d'ailleurs.

Est-ce que tu pourrais mettre un exemple plus parlant ? Je suis un peu perdu.

Je dois partir, j'ai un truc important à faire. Je continue à regarder ton code ce soir :) (mais les autres peuvent participer ;-)).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

ViPHP
ViPHP | 928 Messages

20 juil. 2007, 15:08

Le problème de zeus est simple, t'as une classe :

Code : Tout sélectionner

class Toto { protected $variable; public static function titi() { $new_instance = new Toto; $new_instance->variable = 'valeur'; } }
et il se demande pourquoi on peut assigner une valeur à $new_instance->variable alors qu'il s'agit d'une propriété protégée.
Sachant que ce code ne marche que si on créé une instance de la classe en son sein (mais malgré le fait qu'elle soit en son sein, elle reste indépendante, et par conséquent les éléments protected ne devrait pas être accessible).