PHP: Make my objects have childs
I'm sorry if my question already asked before. I don't know what the search term that match my problem. I've searched 'OOP child', 'PHP object child', etc but I got no clue at all.
So, here we go. I wanted to make something like this:
$school = new School;
var_dump($school);
And resulting something like this:
object(School)#1 (2) {
["name"]=>
string(14) "All Way School"
["object"]=>
object(School)#2 (2) {
["art"]=>
object(School)#3 (1) {
["student"]=>
开发者_StackOverflow中文版 int(25)
}
["law"]=>
object(School)#4 (1) {
["student"]=>
int(30)
}
}
}
See the output. object
has 2 child: art
and law
, each has a child student
. This way, I can access law's total students by $school->object->law->student
. But, I don't know what to write in my class. All I know I can only make $school->name
in my School
class like this:
class School {
$name = "All Way School";
}
I don't know how to make $object
and its child.
Note: I'm just guessing the output. I'm really don't understand how to get it. I'm inspired by SimpleXMLElement.
Edit: I'm replacing $class with $object to prevent confusion.
The OOP 'way' would be to have a different object for each School
, Subject
(you can't use Class
, as it's a reserved keyword) and Student
. Define them as normal, with specific properties:
Class School {
// methods, vars etc
}
Class Subject {
// ...
}
Then, you can create new instances of Class
within School
and assign them to a variable:
Class School {
var $subjects;
function __construct() {
$this->subjects = new Array();
}
}
$mySchool = new School();
$mySchool->subjects[] = new Subject();
Then you can get the subjects using:
$mySchool->subjects[1]->name;
Hope that helps
You can make a child the same way you assigned a name:
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')
);
}
}
You can do the same for the SchoolClass
class, making it contain all the students;
class SchoolClass {
$name;
public function __construct( $name ) {
$this->name = $name; // law, art, etc
$this->students = array(
new SchoolStudent( 2 ),
new SchoolStudent( 5 )
);
}
}
(Note that you would usually not put the students hard-coded in the constructor like this, but rather load them from a data source.)
Then count the students for instance:
$School = new School();
echo count( $School->classes['law']->students );
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);
Will give you exactly this:
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)
If you don't want to type every class by hand, read about overloading in PHP and beautiful __set()
/__get()
methods.
Typecasting can be other solution that fits:
$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);
Which gives you
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)
I understand that all this is not what you're looking for, but I hope that these examples will help you understand your own needs better and ask the right question. Your current question is vague and unclear: even if I gave you literally what you've asked, you ain't going to accept my answer.
You need a seperate class for each object, they can;t all be instances of School
. For example, Your class School
would have two properties, name
and subjects
. Then you would have an class called subject
which contains a name and a numbver of students. Note that I have used the word 'subject' instead of 'class' - this is because 'class' is a reserved word in PHP and even if it weren't, it would get very confusing if you had a class called 'class'.
So you might do something like this:
<?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'
?>
While you could write this in a single class that contains more instances, it doesn't make semantic sense to do so in this situation.
A SimpleXML element is one object that contain children that are instances of itself. This is because that is how XML works - any element can contain any other element (within reason). E.g. you can have <div><div><div>Some Data</div></div></div>
but equally you could just have <div>Some Data</div>
. All those divs are XML elements - they are all the same type of object. They can potentially contain more of themselves, but this situation is rare.
You are dealing with 2 distinct types of object - a School and a Subject. Think of it like the real world - a School won't contain another School, a Suject wont contain another Subject, and a Subject will not exist outside a School.
You could take the above example a step further, and create a class called Student
since this is another distict type. A Student might be contained by a School or a Subject, but it will never contain either of them. Equally, say you had a Book
class, a Student could have one, a Subject could have one, or a School could have one. But a Book would never contain a whole School - it just doesn't make sense.
OOP is all about objects. Think about it in terms of the real world, it will help you make sense of what classes you need, and how they can interact with each other.
精彩评论