Comment utiliser une class dans une autre class?

ViPHP
ViPHP | 4674 Messages

12 oct. 2008, 21:33

Oui tu peux faire quelques choses du genre.
N'utilise jamais le mot-clé global, il est dangereux et assez mal-aimé dans le milieu « professionnel » PHP. Il relève plus d'une bidouille que d'une réelle structure organisée et pensée. Il sert à rendre toutes les données accessibles depuis partout dans le script (et même depuis l'« extérieur »).

D'ailleurs, les mots-clés parent et global n'ont rien en rapport. Quand tu déclares deux méthodes qui ont le même prototype (on parle aussi de profil ou de signature — i.e. même nom, même nombre d'argument etc., mais pas même corps, ça ne rentre pas en compte —) dans une classe A et B (où A hérite de B), et que tu te places dans A, alors, si tu utilises le mot-clé $this, il appellera la dernière méthode déclarée (on parle aussi de pile d'accès, mais on va simplifier). Si tu veux utiliser la méthode supérieure, on utilise le mot-clé parent car elle est forcément placée dans le parent. Un exemple :
class B {

    public function maMethode ( ) { }
}

class A extends B {

    public function maMethode ( ) { }

    public function test ( ) {

        // on appelle maMethode de cette classe.
        $this->maMethode();

        // on appelle maMethode de la classe parente.
        parent::maMethode();
    }
}
Maintenant, si on utilise des méthodes statiques, on n'utilisera pas le mot-clé this mais self. Pourquoi ?
Il faut comprendre que si tu déclares une donnée comme statique, elle n'appartient pas à l'objet mais à la classe. Le mot-clé this fait référence (et c'est pas peu dire) à l'objet lui-même. Le soucis, c'est qu'on ne veut pas appeler l'objet mais la classe, on utilise donc un autre mot-clé : self.
Le cas de parent maintenant. Tu t'es peut-être rendu compte que this peut appeler les méthodes des parents, si et seulement si ces méthodes ne sont pas définies dans la classe fille (là où on travaille). Par exemple si maMethode() était définie dans B mais pas dans A, si on appelle $this->maMethode() depuis A, on appellera maMethode dans B, logique, elle appartient à l'objet, et l'objet est un tout (fille, parent etc.), c'est une grande et belle famille (talala tala …). Impossible donc de faire la différence entre la classe fille et ses parents avec this. On utilise donc parent qui s'utilise comme un mot-clé statique mais qui n'en a pas vraiment le comportement.
this s'utilise dans un contexte objet, self dans un contexte statique, et parent dans les deux contextes. Ça se comprend bien, mais c'est un peu compliqué, on n'entrera pas dans les détails ce soir (déjà parce que je suis naze, que j'ai faim, et que j'ai encore du boulot ;-), tu m'excuseras).

Utiliser une classe statique, c'est sympa, mais pas toujours. Si D a besoin d'être instancier pour son bon fonctionnement, sache qu'il existe un design pattern qui porte le doux petit nom de Singleton (même notion qu'en Mathématiques, i.e. une instance unique d'un objet). En fait, la classe contient sa propre instance et ne peut pas s'instancier sans passer par une méthode statique.
On a quelque chose du genre :
class Singleton {

    // Notre instance.
    // Elle est privée et appartient à la classe.
    private static $_instance = null;

    // Notre constructeur est privée, pas d'instance possible.
    private function __construct ( ) {

        echo 'Je suis construit !';
    }

    // La méthode qui permet de récupérer l'instance.
    // Elle est statique et public.
    public static function getInstance ( ) {

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

        return self::$_instance;
    }
}
À l'utilisation, on comprend vite qu'il faut toujours appeler la méthode getInstance pour obtenir l'instance, mais il n'existera qu'une seule et unique instance de l'objet. C'est très pratique dans des situations assez connues (connexion vers des bases de données par exemple).

Voilà, j'espère avoir répondu suffisamment à ta question, dis moi si je n'ai pas été clair ou assez complet :).
« 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 | 1668 Messages

13 oct. 2008, 12:43

Un léger complément :

$this appel une méthode non static (ou non const, qui est le "static" des variables au seins d'une classe, sâchant si tu fais static $mavariable, c'est de la persistance de variables, donc rien à voir), self:: appel une méthode static ou un attribut const, donc si tu inverse en appellant un const ou un static via $this, et vie-et-versa, tu aura une belle erreur...
Deplus, dans une méthode static, $this n'est pas définit...

Voilà, rien de plus à ajouter votre horreur, euh, honneur :lol:

PS : HyWaN je croyait que l'esprit dominait le corps ? :D
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 4674 Messages

13 oct. 2008, 18:33

$this appel une méthode non static (ou non const, qui est le "static" des variables au seins d'une classe, sâchant si tu fais static $mavariable, c'est de la persistance de variables, donc rien à voir),
Rien compris …
Mais sinon, c'est tout bête une constante de classe. C'est quoi d'abord ? Que se cache derrière le mot-clé const ? C'est tout simplement un attribut de classe public, static et qui est final (donc on ne peut pas le redéfinir dans les enfants). Donc, ces deux lignes sont identiques :
class A {

    const MA_CONSTANTE;
    final public static $MA_CONSTANTE_EMULEE;
}
Bien sûr, quand on appelle une constante, pas besoin de $ (dollars), mais le principe est là : une constante est un attribut de classe (donc statique), qui est public, et déclaré comme final. Cette notion est très clair en Java par exemple.
« 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 | 1668 Messages

13 oct. 2008, 19:23

$this appel une méthode non static (ou non const, qui est le "static" des variables au seins d'une classe, sâchant si tu fais static $mavariable, c'est de la persistance de variables, donc rien à voir),
Rien compris …
Je suis allez un peu vite :

$this appel une méthode non static (ou non const*),

* c'est une constante, un attribut static en gros
( NB : si tu tente static $mavariable, c'est de la persistance de variables, donc rien à voir )

mieu ?
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 4674 Messages

13 oct. 2008, 19:48

Hmmm, là encore, tu n'utilises pas le bon vocabulaire :P. Quand on parle de persistance, on fait régulièrement allusion à la sérialisation de données, et non pas au fait qu'une donnée appartienne à une classe. Une classe n'existe que pendant le temps de l'exécution du programme au maximum (car ça peut être pendant moins de temps : libération de mémoire si l'objet est inutile par exemple), sauf si on rend la classe persistance. Comment ? On transforme la classe en XML, en langage de sérialisation, ou en n'importe-quoi-d'autre-d'unique-et-de-nativement-compréhensible.

Mieux ?
« 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 | 1668 Messages

13 oct. 2008, 20:01

Oui, bon, je retourne bosser moi :lol:

L'essentiel c'est que djtec ne se pose plus de question hein ;)
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

Eléphant du PHP | 451 Messages

13 oct. 2008, 20:26

Oulah ça deviens dur pour mon petit cerveau lol.

HyWaN je croyais que pour appeler une constante fallait utiliser self::
class A 
{
      const MA_CONSTANTE = 'Hello word!';

      function test()
      {
          echo self::MA_CONSTANTE;
      }
}
Du moins c'est ce que j'ai lu sur http://www.manuelphp.com/.

Déjà je pense avoir compris ton premier topic de la page 2 mais je me suis perdu quand tu as parlé de design pattern.

Je pense avoir trouvé la solution à mon sujet de départ mais je voudrais une précision sur une chose:
La fonction __autoload() -> si j'ai bien compris elle sert à charger des class dans une class.
Donc si on charge des class c'est que l'on peut utiliser c'est class dans la class où on a la fonction __autoload()???????

ViPHP
ViPHP | 5924 Messages

14 oct. 2008, 02:05

HyWaN je croyais que pour appeler une constante fallait utiliser self::
Ca oui.
Je pense avoir trouvé la solution à mon sujet de départ mais je voudrais une précision sur une chose:
La fonction __autoload() -> si j'ai bien compris elle sert à charger des class dans une class.
Donc si on charge des class c'est que l'on peut utiliser c'est class dans la class où on a la fonction __autoload()???????
Euh non, elle sert à charger une classe qui n'existe pas. Si une classe n'existe pas, la fonction est appelée, et est censée charger cette classe.

Mammouth du PHP | 19672 Messages

14 oct. 2008, 07:20

...(__autoload)... sert à charger une classe qui n'existe pas. Si une classe n'existe pas, la fonction est appelée, et est censée charger cette classe.
Si je peux me permettre, je vais formuler ça autrement parce que telle quelle, l'explication ne tient pas la route.

Pour simplifier, __autoload est là pour intercepter les créations d'instances de classe, on pourrait comparer ça à un gestionnaire d'évènement, mais sur un évènement coté serveur unique : l'instanciation d'une classe. Si une fonction __autoload a été définie et a été chargée en début de programme, chaque fois que sera rencontré dans le code un "$var = new nomDeMaClasse()", __autoload va le détecter. Cette fonction comporte un paramètre qui est le nom de la classe dont on veut créer une instance. Et bien entendu, on appelle jamais directement cette fonction, le simple fait de créer une instance va formuler cet appel et définir automatiquement la valeur du paramètre.

À charge par contre pour le développeur de construire le code qui sera exécuté lorsque __autoload sera sollicitée. Ça veut dire qu'on peut par exemple définir où aller chercher le fichier de la classe qui peut être déterminé selon son nom. Ou encore on pourrait lancer selon la classe appelée une opération ou une autre à effectuer juste avant. Ou peut-être encore, sur un plan plus pratique, on peut s'en servir pour ne charger exclusivement que les classes dont on a besoin au moment où on en a besoin : on pourrait imaginer que le code défini dans __autoload comporterait un tableau qui détermine où sont situées toutes les classes disponibles, mais plutôt que de tout charger en mémoire, on laisse faire la fonction qui ne chargera que le nécessaire au moment où il y en a besoin.

Plus globalement, l'arrivée de cette fonction dans PHP permet de surcharger ce qui se passait nativement, à savoir que l'appel d'une instanciation de classe était automatique et ne pouvait fonctionner qu'à la condition que le fichier de ladite classe soit au préalable chargé en mémoire avec un include() par exemple. Là, on peut définir l'inclusion dynamiquement dans la fonction __autoload(), virer les include() du reste du code et ajouter facultativement d'autres traitements préalables si nécessaire.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 451 Messages

14 oct. 2008, 18:43

Donc la fonction __autoload() on s'en sert ainsi:
class A extends C
{
       function __autoload()
      {
          require_once 'class_C.php';
      }
}
Au lieu de faire ceci:
class A extends C { }

class C { }

include('class_A.php');
include('class_C.php');
C'est ça??????
Et peut-on charger avec __autoload() la class qui est dans extends??????
(J'espère que je vais pas me faire taper)


Mais on ne peut pas faire ceci par exemple:
class A 
{
       function __autoload()
      {
          require_once 'class_C.php';
      }

      function __construct()
      {
          $c = new C();
      }
}

Mammouth du PHP | 1668 Messages

14 oct. 2008, 18:51

Aie Aie Aie, Caramba :

__autoload, c'est hors POO :
En POO c'est __call :
    public function __call($name, $arguments) {
        // Note : la valeur de $name est sensible à la casse.
        echo "Appel de la méthode '$name' "
             . implode(', ', $arguments). "\n";
    }
http://fr3.php.net/__call

Désolée d'être méchant, mais le bidouillage...
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

Mammouth du PHP | 19672 Messages

14 oct. 2008, 18:59

djtec, je voudrais que tu analyses la chose suivante : si tu crées une méthode __autoload dans une classe, comment créeras-tu une instance de cette même classe ? Et si il n'existe pas d'instance de cette classe, comme créeras-tu les instances éventuelles d'autres classes ? :-k

Tu peux mettre la fonction __autoload() en dehors de tes librairies, et ce serait même beaucoup plus approprié dans un fichier de configuration de ton application, genre le premier fichier qui sera de toutes façons chargé systématiquement avant même qu'un quelconque autre code ne soit exécuté.

Après, le simple fait de créer une instance de classe avec l'opérateur new va être intercepté par __autoload()

Est-ce que cette façon de voir t'éclaire un peu mieux ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

ViPHP
ViPHP | 4674 Messages

14 oct. 2008, 19:03

...(__autoload)... sert à charger une classe qui n'existe pas. Si une classe n'existe pas, la fonction est appelée, et est censée charger cette classe.
Si je peux me permettre, je vais formuler ça autrement parce que telle quelle, l'explication ne tient pas la route.
Bah nan, c'est pas faux ce qu'il dit. Certes, c'est un raccourci, mais c'est juste.
Pour simplifier, __autoload est là pour intercepter les créations d'instances de classe […]
Attention, ce n'est pas seulement pour l'instanciation de classe. Ça peut aussi servir pour un accès statique (un appel). Ainsi : new MaClasse() ou AutreClasse::methode() fonctionnent avec l'auto-chargement.

Ne pas hésiter à lire le manuel, car __autoload ne supporte pas les exceptions par exemple (impossible de jeter une exception dans son corps).
__autoload, c'est hors POO :
En POO c'est __call :
Faux. __call n'a rien à voir avec l'auto-chargement. C'est juste une redirection d'appel de méthode.

__autoload est une fonction, __call est une méthode. Une méthode est une fonction dans une classe si on veut grossir le trait.

Voir le manuel, c'est bien expliquer. Mais je te sens perdu djtec. Reprends les points que tu ne comprends pas et expliques ce que tu veux faire :).
« 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).

Eléphant du PHP | 451 Messages

14 oct. 2008, 19:06

La fonction __call() sert quand on demande une fonction qui n'existe pas dans une class.

Exemple:
<?php
class Manchot
{
     private function __call($method, $arguments)
     {
          echo 'Vous avez appelé la méthode '.$method.'avec les arguments: '.implode(', '.$arguments);
     }
}

$georges = new Manchot();
$georges->voler('Afrique');
?>
Donc __autoload() s'utilise comme une fonction normal hors d'une class.

ViPHP
ViPHP | 4674 Messages

14 oct. 2008, 19:14

Je ne vois pas ce que __call vient faire ici. Katagoto n'avait pas à en parler, c'est hors-sujet. Oublie __call pour l'instant.
Pour répondre à ta question : oui c'est ça.

Revenons à ton problème initial : pourquoi veux-tu utiliser __autoload ?
« 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).