我正在寻找一种用PHP表示家谱的方法。这意味着孩子需要继承两个(或更多)父母。
以下是要求:
这是我的非工作尝试(遗憾的是没有数组作为键):
$tree = array(
'uncle' => false, // no children
array('mom', 'dad') => array(
'me' => false,
array('brother', 'sister-in-law') => array(
'niece' => false
)
)
);
问题是,我如何用这些要求来表示家谱?
答案 0 :(得分:20)
您将无法在单个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";
输出:
约翰与简结婚 比利的父母是简和约翰。
如果图形变大,我们可以递归地遍历图形。这是一个示例树行走功能,它显示了一个基本的家谱。我已经添加了Sara,她的丈夫Mike和他们的儿子Bobby。
$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);
输出:
John&简
.... Sara&迈克
........鲍比
....比利
编辑:以下是@ 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);
}
}
答案 1 :(得分:1)
GEDCOM是用于在不同谱系软件之间交换谱系数据的开放式规范。 GEDCOM文件是纯文本(通常是ANSEL或ASCII),包含有关个人的系谱信息,以及将这些记录链接在一起的元数据。大多数家谱软件支持从GEDCOM格式导入和/或导出。
使用GEDCOM的一个主要优势是,您可以使用Aldfaer (Dutch only),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's data model或Gramps data model。虽然它们不像GEDCOM标准那样常用,但它们可能更适合您的需求。
如果您想使用Gramps数据模型,您可以使用例如。 Gramps PHP exporter将您的数据导出到SQLite数据库中。另请参阅this source,了解如何设计适合Gramps数据模型的数据库。