Précédent   Forum des professionnels en informatique > PHP > Langage > Syntaxe
Syntaxe Forum d'entraide sur la syntaxe de PHP et la POO. Avant de poster -> FAQ syntaxe, Cours d'initiation et cours de POO
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 10/08/2007, 02h54   #1
Membre du Club
 
Inscription : avril 2004
Messages : 77
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : avril 2004
Messages : 77
Points : 50
Points : 50
Envoyer un message via ICQ à Info-Rital Envoyer un message via MSN à Info-Rital Envoyer un message via Yahoo à Info-Rital Envoyer un message via Skype™ à Info-Rital
Par défaut [POO] Portée des objets

Bonjour,
je coince actuellement sur un soucis au niveau de la portée des objets.

J'ai un fichier index.php dans le quel j'instancie un objet de la classe A et un objet de la classe B:
Code :
1
2
$a = new A();
$b = new B();
Dans ma classe B, j'aimerai bien avoir accès à l'objet $a :
Citation:
class B {
function B() {
$a->getVar();
}
}
Cependant cela ne marche pas (je m'en doutais un peu). Maintenant le problème est de trouver un moyen pour pouvoir accèder à cet objet $a instancié dans le même fichier que l'objet $b, dans la classe B.

À part utiliser le mot clé "global" que je serai contraint de rédéclarer dans chaque méthode utilisant l'objet $a, n'y a-t-il pas une autre solution ?

Parce que certe là ça ne semble pas être très important, mais en réalité j'ai pleins d'objets auxquels je voudrai accéder dans pleins de classes et dans pleins de méthodes. Utiliser le mot clé global à chaque fois est assez génant pour moi.
N'y a-t-il pas une autre solution ?

Sinon je peux faire de index.php une classe Index avec deux attributs $this->a (l'objet $a) et $this->b (...) et je fais hériter toute mes classes de Index, et donc je pourrai accéder dans toutes mes classes à mes deux objets comme ça : $this->a->getVar(); par exemple.
Cette solution est elle meilleure ?
Cependant elle m'oblige quand même à : 1) employer $this à chaque fois, et 2) à faire hériter toute mes classes de Index.

Y a t il une solution qui m'aurait échappée ?

Merci d'avance pour vos réponses.


PS : sinon il y a la solution d'utiliser le tableau $GLOBALS et de mapper chaque valeur dans une variable, genre $a = $GLOBALS['a'] mais bof bof.
Info-Rital est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 09h00   #2
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Ben tu as la première : le mot clé global partout dans les méthodes. Effectivement ca n'est pas génial et puis il faut s'assurer que la variable est vraiment déclarée partout etc, ca peut poser des problèmes.

Ensuite tu as la solution de passer cette instance de classe en paramètre de chaque méthode. C'est plus clair parce que tu vois le paramètre, quand tu appelles la fonction tu SAIS que tu as besoin de cette autre classe, qu'elles est instanciée vu que tu la passes en paramètre. Mais ca peut etre ennuyeux si t'as 200 méthodes et trois classes utilisées dans chaque méthode.

Tu peux aussi passer cette instance (de la classe A) au constructeur de la classe B. Comme ca tu ne le passes qu'une fois en paramètre, lors du constructeur, et donc ta classe B contient une "instance de la classe A" dans ses variables.

Et puis il y a effectivement la solution de faire une classe supérieure qui se charge de contenir une instance de chacune de tes classes indispensables.

Perso je pencherai pour la solution du constructeur dans la majorité des cas mais parfois ca n'est pas adapté.
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 09h08   #3
Membre Expert
 
Avatar de stailer
 
Homme Jean-François CAMBOT
Développeur informatique
Inscription : mars 2003
Messages : 842
Détails du profil
Informations personnelles :
Nom : Homme Jean-François CAMBOT
Âge : 34
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : mars 2003
Messages : 842
Points : 1 110
Points : 1 110
Il ne faudrait pas passer plutôt par un multition ou un truc du genre :

function B()
{
$inst = A::getInstance();

$mavar = $inst->getVar();
}


Je dis ça un peu à l'arrache, voir le cours sur ce site concernant les multitons
__________________
.o0o__St@iLeR__oOo.

Chef de projet / Développeur

Silverlight / ASP.NET MVC - MCP ASP.NET 4
Zend Framework / Ajax (Jquery et ExtJS)
Adobe Flash Builder (Flex)

Ma librairie pour faire communiquer PHP et Silverlight "à la" WCF : http://code.google.com/p/phpservices-silverlight/
stailer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 14h24   #4
Membre habitué
 
Inscription : mai 2002
Messages : 101
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : mai 2002
Messages : 101
Points : 106
Points : 106
Effectivement, le plus clair me semble de passer une instance de A au constructeur de B.

Le global, ça devient vite le souk (et c'est pas propre). Ca peut se justifier si tu as des dépendances croisées (genre A utilise B et B utilise A), encore que...

Le passage en paramètre, ça fonctionne bien pour un appel ou deux, mais si tu as toujours besoin de A, ça peut vite devenir lourd à implémenter
Cold Hand est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 14h37   #5
Invité de passage
 
Inscription : juillet 2007
Messages : 3
Détails du profil
Informations forums :
Inscription : juillet 2007
Messages : 3
Points : 3
Points : 3
Sur le coup, je pensais comme koopajah, passer l'instance de A au constructeur de la classe B. Mais a ce moment la est ce que cela crée un pointeur vers l'instance A dans B, ou est ce que cela créer une autre instance de A propre a B ?

Sans compter que si on veux faire l'invers (utiliser B das A) cette solution n'est pas valable étant donner qu'il faudra bien en instancier un avant l'autre ^^.
H_leOuf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 14h40   #6
Membre habitué
 
Inscription : mars 2007
Messages : 87
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : mars 2007
Messages : 87
Points : 109
Points : 109
salut,

tu peux aussi utilisez un registre (registry). Pas mal utiliser dans les frameworks. Exemple:
Code :
1
2
3
4
5
6
7
8
9
10
 
class A { function getVar() {} ... }
 
Registry::register('a', new A());
 
class B {
function getVar() {
Registry::get('a')->getVar();
}
}
en fait Registry est une classz "statique" dans lequel tu peux enregistrer des instances de classes et les nommer. Tu peux ensuite accéder à ces instances en utilisant leur nom.
supergogol est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 14h41   #7
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Tu passes ce qu'on appelle une référence, tu ne crées pas une nouvelle instance.

Et j'ai du mal a me rappeler d'un cas ou deux classes ont besoin mutuellement l'une de l'autre.
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h25   #8
Membre habitué
 
Inscription : mai 2002
Messages : 101
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : mai 2002
Messages : 101
Points : 106
Points : 106
Citation:
Envoyé par koopajah
Et j'ai du mal a me rappeler d'un cas ou deux classes ont besoin mutuellement l'une de l'autre.
J'ai pas de cas "utile" en tête, mais prenons par exemple une classe Enfant et une classe Parent. Selon comment on utilise ces deux classes, elles peuvent mutuellement liées. (De mémoire, un prof nous avait donné l'exemple d'une classe Poule et d'une classe Oeuf, chacune devant être instanciée avant l'autre... quel humour ces profs )

De manière plus générale, tout système représenté sous forme d'une liste chaînée bi-directionelle implique que A contient une référence à B et B une référence à A. Bien sûr, c'est beaucoup plus simple dans ce cas d'instancier les deux objets et de définir ensuite leur relation via un "set".
Cold Hand est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h30   #9
Membre habitué
 
Avatar de Amnesiak
 
Geoffray
Inscription : août 2002
Messages : 137
Détails du profil
Informations personnelles :
Nom : Geoffray
Âge : 31
Localisation : Belgique

Informations forums :
Inscription : août 2002
Messages : 137
Points : 122
Points : 122
Si j'ai bien compris, le passage d'objets se fait toujours par référence. Pour forcer un passage par valeur, il faut utiliser le mot clé clone
Amnesiak est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h35   #10
Membre habitué
 
Inscription : mai 2002
Messages : 101
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : mai 2002
Messages : 101
Points : 106
Points : 106
Exact. Attention donc aux mauvaises surprises si on modifie l'objet dans une méthode à laquelle il a été passé...
Cold Hand est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h36   #11
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Citation:
Envoyé par Amnesiak
Si j'ai bien compris, le passage d'objets se fait toujours par référence. Pour forcer un passage par valeur, il faut utiliser le mot clé clone
Si on lit la documentation on voit que les arguments sont toujours passés par valeur faut utiliser & devant pour passer par référence.
Je le fais tellement souvent que j'avais oublié.
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h39   #12
Membre habitué
 
Inscription : mai 2002
Messages : 101
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : mai 2002
Messages : 101
Points : 106
Points : 106
Citation:
Envoyé par koopajah
Si on lit la documentation on voit que les arguments sont toujours passés par valeur faut utiliser & devant pour passer par référence.
Je le fais tellement souvent que j'avais oublié.
Ah ?? J'aurais donné la main d'un pote à couper que c'était comme en C# ou en Java et que c'était passé par référence... C'est marqué où que c'est par valeur ?
Cold Hand est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h41   #13
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Citation:
Envoyé par Cold Hand
Ah ?? J'aurais donné la main d'un pote à couper que c'était comme en C# ou en Java et que c'était passé par référence... C'est marqué où que c'est par valeur ?
J'aurai pensé que c'était comme le C/C++ moi : que pour les instances d'objet, les tableaux c'était par défaut par référence (comme tu utilises les pointeurs en C/C++ pour ce genre de données c'est par référence).
Mais d'après la doc
Citation:
Envoyé par doc
Par défaut, les arguments sont passés à la fonction par valeur (donc vous pouvez changer la valeur d'un argument dans la fonction, cela ne change pas sa valeur à l'extérieur de la fonction). Si vous voulez que vos fonctions puissent changer la valeur des arguments, vous devez passer ces arguments par référence.

Si vous voulez qu'un argument soit toujours passé par référence, vous pouvez ajouter un '&' devant l'argument dans la déclaration de la fonction :
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h49   #14
Membre habitué
 
Inscription : mai 2002
Messages : 101
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : mai 2002
Messages : 101
Points : 106
Points : 106
mmh... La doc parle du passage d'argument pour les fonctions, je ne sais pas si les constructeurs sont englobés dans le tas... D'autant que la phrase

Citation:
La valeur par défaut d'un argument doit obligatoirement être une constante, et ne peut être ni une variable, ni un membre de classe, ni un appel de fonction.
Me laisse sceptique. Bon, à tester quoi...
Cold Hand est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 15h56   #15
Membre du Club
 
Inscription : avril 2004
Messages : 77
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : avril 2004
Messages : 77
Points : 50
Points : 50
Envoyer un message via ICQ à Info-Rital Envoyer un message via MSN à Info-Rital Envoyer un message via Yahoo à Info-Rital Envoyer un message via Skype™ à Info-Rital
Merci pour vos réponses.

Je constate qu'il n'y aucune solution vraiment "simple" et "propre", alors je me dis que je prends peut-être le problème à l'envers.
Peut-être est-ce un defaut de conception de ma part ?

En faite, j'ai crée une classe SQLManager (une couche d'asbtraction à la base, je sais qu'il existe PDO, mais là c'est un truc plus léger et adapté à ce dont j'ai besoin).
J'ai une méthode query() pour executer des requetes. J'ai donc instancié un objet de cette classe : $sql = new SQLManager(); et j'aimerai bien pouvoir faire partout dans mon code $sql->query(); comme j'aurai fait pg_query().
Après j'ai d'autre classe dans le genre, comme Game : $game = new Game(); et j'aimerai pouvoir utiliser les methodes de mon objet $game partout dans mes autres classes.
Vous voyez ?
Je pense que c'est un des interêts de la POO et que je ne suis pas le seul à faire ça. Mais peut-être que je m'y prends mal.

Est-ce qu'il serait plus judicieux de déclarer mes methodes en static et y accéder avec un simple SQLManager::query();, mais dans ce cas là coment faire pour les attributs de classe....? Genre dans ma classe Site, je charge un fichier de configuration avec loadConfig(); et je remplis les attributs $site->default_theme, $site->default_lang etc...que j'ai besoin à divers endroits du code.

Est ce qu'il serait plus judicieux de créer un nouvel objet de ma classe SQLManager dans chaque classe...?
Mais le problème reste le même pour ma classe Site et ses attributs...
Info-Rital est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 16h05   #16
Modérateur
 
Avatar de mathieu
 
Inscription : juin 2003
Messages : 4 893
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 4 893
Points : 4 466
Points : 4 466
je fais quelque chose dans le même genre quand j'utilise des bases de données dans mon code, j'ai une classe BDD avec çà :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
class BDD
{
    function & obtientConnexion()
    {
        static $connexion;
 
        if (!isset($connexion)) {
            $connexion =& new BDD();
        }
 
        return $connexion;
    }
et ensuite dans les classes des objets de ma base je fais "$bdd =& BDD::obtientConnexion();" pour récupérer la connexion à ma base de données
et comme ça j'ai juste besoin de me connecter une seule fois à la base, ce qui économise des ressources
__________________
Modérateur PHP
mathieu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 16h11   #17
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Citation:
Envoyé par mathieu
et ensuite dans les classes des objets de ma base je fais "$bdd =& BDD::obtientConnexion();" pour récupérer la connexion à ma base de données
et comme ça j'ai juste besoin de me connecter une seule fois à la base, ce qui économise des ressources
C'est le principe du pattern singleton ca non? Enfin quelqu'un a parlé plus tot de pattern dans ce thread mais je pense qu'il y a eu confusion. LE but c'est de t'assurer que dans tous tes scripts tu as 0 ou 1 instance de ta classe de base de données en gros.
Moi je dis +1 !
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2007, 16h29   #18
Modérateur
 
Avatar de mathieu
 
Inscription : juin 2003
Messages : 4 893
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 4 893
Points : 4 466
Points : 4 466
Citation:
Envoyé par koopajah
C'est le principe du pattern singleton ca non?
oui c'est ça

en cadeau la version PHP 5 puisque je suis en train de faire des tests dessus
Code :
1
2
3
4
5
6
7
8
9
10
11
12
class BDD
{
    public static function obtientConnexion()
    {
        if (!isset(self::$bdd)) {
            self::$bdd = new BDD();
        }
 
        return self::$bdd;
    }
 
    private static $bdd;
__________________
Modérateur PHP
mathieu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2007, 11h16   #19
Membre Expert
 
Avatar de stailer
 
Homme Jean-François CAMBOT
Développeur informatique
Inscription : mars 2003
Messages : 842
Détails du profil
Informations personnelles :
Nom : Homme Jean-François CAMBOT
Âge : 34
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : mars 2003
Messages : 842
Points : 1 110
Points : 1 110
Bah oui, singleton ou multiton, c'ets ce que je dis dans le 3ème message laissé dans ce post... mais apparement il est passé à la trappe lol
__________________
.o0o__St@iLeR__oOo.

Chef de projet / Développeur

Silverlight / ASP.NET MVC - MCP ASP.NET 4
Zend Framework / Ajax (Jquery et ExtJS)
Adobe Flash Builder (Flex)

Ma librairie pour faire communiquer PHP et Silverlight "à la" WCF : http://code.google.com/p/phpservices-silverlight/
stailer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2007, 03h31   #20
Membre du Club
 
Inscription : avril 2004
Messages : 77
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : avril 2004
Messages : 77
Points : 50
Points : 50
Envoyer un message via ICQ à Info-Rital Envoyer un message via MSN à Info-Rital Envoyer un message via Yahoo à Info-Rital Envoyer un message via Skype™ à Info-Rital
Merci pour vos réponses.

J'ai finalement adopté le pattern Registry, qui est +/- ce que j'avais besoin.
Info-Rital est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 23h16.


 
 
 
 
Partenaires

Hébergement Web