2011-09-05 3 views
2

Je suis désolé si ma question déjà posée avant. Je ne sais pas quel terme de recherche correspond à mon problème. J'ai cherché 'OOP child', 'PHP object child', etc mais je n'ai aucune idée du tout.PHP: Faire mes objets ont des enfants

Alors, c'est parti. Je voulais faire quelque chose comme ceci:

$school = new School; 
var_dump($school); 

Et résultant quelque chose comme ceci:

object(School)#1 (2) { 
    ["name"]=> 
    string(14) "All Way School" 
    ["object"]=> 
    object(School)#2 (2) { 
    ["art"]=> 
    object(School)#3 (1) { 
     ["student"]=> 
     int(25) 
    } 
    ["law"]=> 
    object(School)#4 (1) { 
     ["student"]=> 
     int(30) 
    } 
    } 
} 

Voir la sortie. object a 2 enfants: art et law, chacun a un enfant student. De cette façon, je peux accéder au total des étudiants de la loi par $school->object->law->student. Mais, je ne sais pas quoi écrire dans ma classe. Tout ce que je sais que je ne peux faire $school->name dans ma School classe comme ceci:

class School { 
    $name = "All Way School"; 
} 

Je ne sais pas comment faire $object et son enfant.

Remarque: Je ne fais que deviner la sortie. Je ne comprends vraiment pas comment l'obtenir. Je suis inspiré par SimpleXMLElement. Editer: Je remplace $ class par $ object pour éviter toute confusion.

Répondre

2

Le POO « chemin » serait d'avoir un objet différent pour chaque School, Subject (vous ne pouvez pas utiliser Class, car il est un mot-clé réservé) et Student. les définir comme d'habitude, avec des propriétés spécifiques:

Class School { 
    // methods, vars etc 
} 

Class Subject { 
    // ... 
} 

Ensuite, vous pouvez créer de nouvelles instances de Class au sein School et les assigner à une variable:

Class School { 

    var $subjects; 

    function __construct() { 
     $this->subjects = new Array(); 
    } 

} 

$mySchool = new School(); 

$mySchool->subjects[] = new Subject(); 

Ensuite, vous pouvez obtenir les sujets en utilisant:

$mySchool->subjects[1]->name; 

espoir qui aide

2

Vous pouvez faire un enfant de la même façon que vous avez attribué un nom:

class School { 
    $name = "All Way School"; 

    public function __construct() { // executed when creating a new School object 
     $this->classes = array(
      'art' => new SchoolClass('art'), 
      'law' => new SchoolClass('law') 
     ); 
    } 
} 

Vous pouvez faire la même chose pour la classe SchoolClass, ce qui en fait contenir tous les élèves;

class SchoolClass { 
    $name; 

    public function __construct($name) { 
     $this->name = $name; // law, art, etc 
     $this->students = array(
      new SchoolStudent(2), 
      new SchoolStudent(5) 
     ); 
    } 
} 

(Notez que vous généralement pas mettre les élèves codées en dur dans le constructeur comme celui-ci, mais plutôt de les charger à partir d'une source de données.)

comptent ensuite les étudiants par exemple:

$School = new School(); 
echo count($School->classes['law']->students); 
+0

Mais l'art et la loi est un objet différent, non? –

+0

@Dimas: Il s'agit certainement d'une instance d'objet différente, mais pas nécessairement d'un objet différent. – Tomalak

0

Vous avez besoin d'une classe séparée pour chaque objet, ils peuvent tous être des instances de School. Par exemple, votre classe School aurait deux propriétés, name et subjects. Ensuite, vous auriez une classe appelée subject qui contient un nom et un numbver d'étudiants.Notez que j'ai utilisé le mot 'sujet' au lieu de 'classe' - parce que 'classe' est un mot réservé en PHP et même si ce n'était pas le cas, cela deviendrait très confus si vous aviez une classe appelée 'classe' .

Alors vous pourriez faire quelque chose comme ceci:

<?php 

    class School { 

    public $name; 
    public $subjects = array(); 

    function __construct ($name) { 
     $this->name = $name; 
    } 

    function addSubject ($subject) { 
     // Adds a new subject object 
     if (is_string($subject)) $subject = new Subject($subject); 
     $this->subjects[$subject->name] = $subject; 
    } 

    function getSubjectByName ($name) { 
     // returns a Subject object or FALSE on failure 
     return (isset($this->subjects[$name])) ? $this->subjects[$name] : FALSE; 
    } 

    function getStudentsBySubjectName ($name) { 
     // returns number of students for a subject or FALSE on failure 
     return (isset($this->subjects[$name])) ? $this->subjects[$name]->numberOfStudents : FALSE; 
    } 

    // ... more methods 

    } 

    class Subject { 

    public $name; 
    public $numberOfStudents; 

    function __construct ($name, $students = 0) { 
     $this->name = $name; 
     $this->numberOfStudents = $students; 
    } 

    // ... more methods 

    } 

    $school = new School('Useless City High'); 
    $school->addSubject(new Subject('Math', 2)); 
    $school->addSubject('Stupidity Studies'); 
    $school->subjects['Stupidity Studies']->numberOfStudents = 65; 
    $school->addSubject(new Subject('Law')); 
    var_dump($school); 

    $math = $school->getSubjectByName('Math'); 
    echo $math->numberOfStudents; // outputs '2' 
    echo $school->getStudentsBySubjectName('Math'); // outputs '2' 

    $stupidity = $school->subjects['Stupidity Studies']; 
    echo $stupidity->numberOfStudents; // outputs '65' 
    echo $school->getStudentsBySubjectName('Stupidity Studies'); // outputs '65' 

    echo $school->getStudentsBySubjectName('Law'); // outputs '0' 
    echo $school->subjects['Law']->numberOfStudents; // outputs '0' 

?> 

Alors que vous pouvez écrire ceci dans une seule classe qui contient plus de cas, il n'a pas de sens sémantique de le faire dans cette situation.

Un élément SimpleXML est un objet qui contient des enfants qui sont des instances de lui-même. C'est parce que c'est ainsi que fonctionne XML - n'importe quel élément peut contenir n'importe quel autre élément (dans des limites raisonnables). Par exemple. vous pouvez avoir <div><div><div>Some Data</div></div></div> mais vous pourriez également avoir <div>Some Data</div>. Tous ces divs sont des éléments XML - ils sont tous du même type d'objet. Ils peuvent potentiellement contenir plus d'eux-mêmes, mais cette situation est rare.

Vous avez affaire à 2 types d'objets distincts: une école et un sujet. Pensez-y comme le monde réel - une école ne contiendra pas une autre école, un sujet ne contiendra pas un autre sujet, et un sujet n'existera pas en dehors d'une école.

Vous pouvez prendre l'exemple ci-dessus un peu plus loin, et créer une classe appelée Student puisqu'il s'agit d'un autre type distict. Un étudiant peut être contenu par une école ou un sujet, mais il ne contiendra jamais l'un ou l'autre. De même, disons que vous avez eu une classe Book, un étudiant pourrait en avoir un, un sujet pourrait en avoir un, ou une école pourrait en avoir un. Mais un livre ne contiendrait jamais toute une école - cela n'a tout simplement aucun sens.

La POO est une question d'objets. Pensez-y en termes de monde réel, cela vous aidera à comprendre les classes dont vous avez besoin et comment elles peuvent interagir les unes avec les autres.

+0

Donc, il ne peut pas être dans une instance d'objet comme simplexml fait? –

+0

Voir ma modification ci-dessus – DaveRandom

+0

OK alors. Je me demandais juste pourquoi simplexml et (object) typecasting font toujours son enfant dans la même instance d'objet, 'SimpleXMLElement' et' stdClass'. –

2
class School { 
    public $name, $class; 
    public function __construct() { 
     $this->class = new SchoolClass(); 
     $this->name = "All Way School"; 
    } 
} 

class SchoolClass { 
    public $art, $law; 
    public function __construct() { 
     $this->art = new SchoolStudent(25); 
     $this->law = new SchoolStudent(30); 
    } 
} 

class SchoolStudent { 
    public $student; 
    public function __construct($student) { 
     $this->student = $student; 
    } 
} 

$school = new School(); 

var_dump($school); 
var_dump($school->class->law->student); 

vous donnera exactement ceci:

object(School)#1 (2) { 
    ["name"]=> 
    string(14) "All Way School" 
    ["class"]=> 
    object(SchoolClass)#2 (2) { 
    ["art"]=> 
    object(SchoolStudent)#3 (1) { 
     ["student"]=> 
     int(25) 
    } 
    ["law"]=> 
    object(SchoolStudent)#4 (1) { 
     ["student"]=> 
     int(30) 
    } 
    } 
} 
int(30) 

Si vous ne voulez pas taper toutes les classes à la main, lisez overloading in PHP belles et méthodes __set()/__get().

Transtypage peut être autre solution adaptée:

$school = (object) array(
    "name" => "All Way School", 
    "object" => (object) array(
    "art" => (object) array("student" => 25), 
    "law" => (object) array("student" => 30), 
), 
); 
var_dump($school); 
var_dump($school->object->law->student); 

Ce qui vous donne

object(stdClass)#4 (2) { 
    ["name"]=> 
    string(14) "All Way School" 
    ["object"]=> 
    object(stdClass)#3 (2) { 
    ["art"]=> 
    object(stdClass)#1 (1) { 
     ["student"]=> 
     int(25) 
    } 
    ["law"]=> 
    object(stdClass)#2 (1) { 
     ["student"]=> 
     int(30) 
    } 
    } 
} 
int(30) 

Je comprends que tout cela est pas ce que vous cherchez, mais j'espère que ces exemples vous aider à mieux comprendre vos propres besoins et à poser la bonne question. Votre question actuelle est vague et peu claire: même si je vous ai donné littéralement ce que vous avez demandé, vous n'allez pas accepter ma réponse.

+0

+1 Excellente réponse! Notez que vous pouvez utiliser "class" en tant que propriété. – Herbert

+0

+1 J'aime la méthode de typage. Très très bonne réponse! –

+0

Oh, mais l'objet (objet) ne fonctionne pas dans une classe. Sad :( Je pense que je dois utiliser la première –

Questions connexes