Вы не сможете сделать все это за один array()
, как это. Вы можете настроить деревья таким образом, но для создания более сложных графиков с несколькими родителями и другими отношениями требуется несколько строк кода.
Это очень поможет, если вы добавите в это ОО. Давайте создадим класс Person
, чтобы помочь управлять отношениями. По сути, у нас есть люди и их отношения с другими людьми, поэтому мы начнем там.
Персональный класс
Я представляю себе, что у каждого человека есть множество отношений. Этот массив сначала будет проиндексирован по типу отношений, например, «родители» или «дети». Тогда каждая запись будет массивом Person
с.
class Person {
var $name, $relations;
function __construct($name) {
$this->name = $name;
$this->relations = array();
}
function addRelation($type, $person) {
if (!isset($this->relations[$type])) {
$this->relations[$type] = array();
}
$this->relations[$type][] = $person;
}
// Looks up multiple relations, for example "parents".
function getRelations($type) {
if (!isset($this->relations[$type])) {
return array();
}
return $this->relations[$type];
}
// Looks up a single relation, for example "spouse".
function getRelation($type) {
$relations = $this->getRelations($type);
return empty($relations) ? null : $relations[0];
}
function __toString() {
return $this->name;
}
Дружественные сумматоры и геттеры
Используя вышеперечисленное в качестве основы, мы можем добавить некоторые более дружественные методы. В качестве иллюстрации мы рассмотрим отношения родитель / ребенок и супруги.
function addParents($mom, $dad) {
$mom->addChild($this);
$dad->addChild($this);
}
function addChild($child) {
$this ->addRelation('children', $child);
$child->addRelation('parents', $this);
}
function addSpouse($spouse) {
$this ->addRelation('spouse', $spouse);
$spouse->addRelation('spouse', $this);
}
function getParents () { return $this->getRelations('parents'); }
function getChildren() { return $this->getRelations('children'); }
function getSpouse () { return $this->getRelation ('spouse'); }
}
Создание людей
Теперь мы можем создать пару человек и установить их отношения. Давайте попробуем Билли и его родителей Джона и Джейн.
$john = new Person('John');
$jane = new Person('Jane');
$billy = new Person('Billy');
$john ->addSpouse ($jane);
$billy->addParents($jane, $john);
И мы можем проверить их отношения так:
echo "John is married to " . $john->getSpouse() . ".\n";
echo "Billy's parents are " . implode(" and ", $billy->getParents()) . ".\n";
Выход:
Джон женат на Джейн.
Родители Билли - Джейн и Джон.
Отображение родословной
Мы можем рекурсивно пройти по графику, если он станет больше. Вот пример функции обхода дерева, которая отображает элементарное генеалогическое дерево. Я добавил Сара, ее мужа Майка и их сына Бобби.
$john = new Person('John');
$jane = new Person('Jane');
$sara = new Person('Sara');
$mike = new Person('Mike');
$bobby = new Person('Bobby');
$billy = new Person('Billy');
$john ->addSpouse ($jane);
$sara ->addParents($jane, $john);
$sara ->addSpouse ($mike);
$bobby->addParents($sara, $mike);
$billy->addParents($jane, $john);
function displayFamilyTree($root, $prefix = "") {
$parents = array($root);
if ($root->getSpouse() != null) {
$parents[] = $root->getSpouse();
}
echo $prefix . implode(" & ", $parents) . "\n";
foreach ($root->getChildren() as $child) {
displayFamilyTree($child, "....$prefix");
}
}
displayFamilyTree($john);
Выход:
Джон и Джейн
.... Сара и Майк
........ Бобби
.... Билли
Редактировать: Вот комментарий @ Wrikken ниже, воспроизведенный для удобства чтения:
Об этом действительно. ИМХО, хотя добавьте дату «до» в каждое отношение (возможно, NULL для без конца). Происходят разводы, как и усыновление, и т. Д. Кроме того: я бы добавил обратные типы & ping-back к функции addRelation()
:
function addRelation($type, $person, $reverseType, $pingback = false) {
if (!isset($this->relations[$type])) {
$this->relations[$type] = array();
}
if (!in_array($person, $this->relations[$type], true)) {
$this->relations[$type][] = $person;
}
if (!$pingback) {
$person->addRelation($reverseType, $this, $type, true);
}
}