Допустим, я хочу хранить собак в таблице базы данных, у каждой собаки есть свой подкласс в PHP.
В основном я хочу избежать хранения / перечисления имен подклассов в разных местах кода. Какой подход к этому был бы хорош для ООП?
abstract class Dog {
protected $data;
public function __construct($data) {
$this->data = $data;
}
public function name() {
return $this->data["name"];
}
abstract public function breed();
}
class GermanShepherd extends Dog {
public function breed() {
return _("German Shepherd");
}
}
class BullDog extends Dog {
public function breed() {
return _("Bulldog");
}
}
Теперь у меня есть этот класс, который обрабатывает группы объектов (т.е. собак):
class Dogs {
public static function getDogs() {
// ...
$ret = array();
while ($row = mysql_fetch_assoc()) {
switch ($row["type"]) { // I could do this using a lookup array
case "shepherd": $dog = "GermanShepherd"; break;
case "bulldog": $dog = "Bulldog"; break;
}
$ret[] = new $dog($row);
}
return $ret;
}
}
И я хотел бы использовать этот класс, чтобы получить типы собак в моем представлении (особенно для формы add dog ) вместо перечисления имен классов:
?><form><select name="type"><?php
foreach (array("GermanShepherd", "Bulldog") as $dog) { // here I would like to do avoid listing the class names again
?><option value="<?=$dog ?>"><?php
$d = new $dog; // actually I can't instantiate the class here because I don't have any data at this point
echo $d->name();
?></option><?php
}
?></select></form><?php
Я хотел бы включить это в класс Dogs
, что-то вроде этого:
class Dogs {
private static $dogs = array(
"shepherd" => "GermanShepherd",
"bulldog" => "Bulldog",
);
public static function getDogs() {
// ...
$ret = array();
while ($row = mysql_fetch_assoc()) {
$dog = self::$dogs[$row["type"]];
$ret[] = new $dog($row);
}
return $ret;
}
public static function getDogTypes() {
return array_values(self::$dogs);
}
}
?><form><select name="type"><?php
foreach (Dogs::getDogTypes() as $dog) {
?><option value="<?=$dog ?>"><?php
$d = new $dog; // here I still need to instantiate the class and I don't have any data to provide it with
echo $d->name();
?></option><?php
}
?></select></form><?php
Пока что это будет работать, но что, если мне понадобится больше информации, специфичной для класса, например, когда у меня будет больше полей, специфичных для типа собаки?
foreach (Dogs::getDogTypes() as $dog) {
$d = new $dog; // instantiate again?
foreach ($d->formFields() as $f) { // I wouldn't do it like this, just putting this here for demonstrative purposes
echo $f;
}
}
Я думаю, что часть проблемы заключается в том, что мне нужно иметь возможность использовать свои классы с данными базы данных и без них: все кажется очень разумным, когда у меня есть данные из таблицы базы данных, но мне также нужны данные, когда Я создаю форму при создании новой собаки.
Спасибо за ваши идеи!