Intereting Posts
PHP – строка для многомерного массива Как я могу использовать PHP для перенаправления пользователей IE на определенную страницу? Расчет рабочих часов Получить идентификатор продукта и тип продукта в пурпуре? sql UPDATE row :: оставить текущее значение, если вход пустой Как добавить новые поля в профиль пользователя в Drupal 7 программно Загрузить HTML-код, содержащий пространства имен с DOMDocument Создайте сводную таблицу сравнения на основе дат сайта Как найти адрес в Великобритании по номеру дома и почтовому индексу? Как удалить файлы из каталога на основе даты создания в php? PDO получить данные из базы данных Форма Symfony2 – от многих до многих, поскольку текст вызывает ошибки Лучшая практика использования обработки исключений PHP Любой способ изменить URL-адрес заголовка без перезагрузки? PHP: Есть ли команда, которая может удалить содержимое файла без его открытия?

Структура данных «Семейное древо»

Я ищу способ представления генеалогического дерева в PHP. Это означает, что детям необходимо наследовать от двух (или более) родителей.

Вот требования:

  • 1, 2 и более родителей
  • Бонусные баллы, если я могу прикрепить метаданные, например, фамилию или статус отношений

Вот моя нерабочая попытка (без массивов в виде ключей, к сожалению):

$tree = array( 'uncle' => false, // no children array('mom', 'dad') => array( 'me' => false, array('brother', 'sister-in-law') => array( 'niece' => false ) ) ); 

Вопрос в том, как я могу представить генеалогическое древо с этими требованиями?

Вы не сможете сделать все это в одном array() . Вы можете настроить такие деревья, но для создания более сложных графиков с несколькими родителями и другими отношениями требуется несколько строк кода.

Это очень поможет, если вы выбросите OO. Давайте создадим класс Person чтобы помочь управлять отношениями. По сути, у нас есть люди и их отношения с другими людьми, поэтому мы начнем там.

Класс человека

Я думаю, что каждый человек имеет множество отношений. Этот массив будет сначала индексироваться по типу отношений, например «родители» или «дети». Каждая запись будет представлять собой массив Person s.

 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); } } 

GEDCOM – это открытая спецификация для обмена генеалогическими данными между различными программами генеалогии. Файл GEDCOM представляет собой простой текст (обычно ANSEL или ASCII), содержащий генеалогическую информацию о физических лицах и метаданные, связывающие эти записи вместе. Большинство программ генеалогии поддерживает импорт и / или экспорт в формат GEDCOM.

Основным преимуществом использования GEDCOM является то, что вы могли бы использовать настольные программы, такие как Aldfaer (только для голландцев) , Gramps или Legacy Family Tree, а также онлайн-инструменты, такие как Geneanet, для создания или изменения вашего генеалогического древа и сравнения его с генеалогическими деревьями других ,

Еще одно важное преимущество использования формата GEDCOM заключается в том, что в вашем распоряжении имеются библиотеки на нескольких языках программирования для сохранения и загрузки ваших данных. Примерами библиотек PHP будут GEDCOM Import / Export-Filter , GenealogyGedcom или PHP GEDCOM .

Используя PHP GEDCOM, чтение и разбор GEDCOM-файла будет таким же простым, как это:

 $parser = new \PhpGedcom\Parser(); $gedcom = $parser->parse('gedcom.ged'); 

Основным недостатком использования GEDCOM является то, что формат данных GEDCOM построен вокруг ядерной семьи, а это означает, что стандарт ограничен в поддержке нетрадиционных семейных структур, таких как однополые партнерства, смешанные семьи или совместное проживание. Хотя для поддержки такого типа связей можно расширить GEDCOM, для таких расширений ограничена возможность взаимодействия между различными программами.

Еще одним серьезным недостатком использования GEDCOM является то, что файлы GEDCOM являются монолитными. Если у вас есть набор данных из тысяч людей или вы хотите часто менять структуру данных, вы, вероятно, столкнетесь с проблемами производительности. Особенно в таких случаях лучше хранить ваши данные в базе данных. Тем не менее, это не означает, что GEDCOM бесполезен. В таких случаях вам может потребоваться использовать схему базы данных на основе формата GEDCOM, которая позволяет вам импортировать / экспортировать базу данных и формат GEDCOM. Для этого существуют и библиотеки. Пример Oxy-Gen .


Альтернативой GEDCOM будет модель данных GenTech или модель данных Gramps . Хотя они не так широко используются как стандарт GEDCOM, они могут лучше соответствовать вашим потребностям.

Если вы хотите использовать модель данных Gramps, вы можете использовать, например. экспортер Gramps PHP для экспорта ваших данных в базу данных SQLite. См. Также этот источник о том, как создать базу данных, подходящую для модели данных Gramps.