7

我正在寻找一种在 PHP 中表示家谱的方法。这意味着孩子需要从两个(或更多)父母那里继承。

以下是要求:

  • 1、2 或更多父母
  • 如果我可以附加诸如姓氏或关系状态之类的元数据,则可以加分

这是我的非工作尝试(遗憾的是,没有数组作为键):

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

问题是,我如何代表具有这些要求的家谱?

4

2 回答 2

21

您将无法array()像那样一次性完成所有工作。您可以像这样设置树,但是设置具有多个父级和其他关系的更复杂的图形需要多行代码。

如果您对此进行一些 OO 操作,将会有很大帮助。让我们创建一个Person类来帮助管理这些关系。从根本上说,我们已经掌握了人以及他们与其他人的关系,所以我们将从那里开始。

人物类

我想象的是每个人都有一系列的关系。该数组将首先按关系类型进行索引,例如“父母”或“孩子”。然后每个条目将是一个Persons 数组。

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

输出:

约翰和简
....萨拉和迈克
........鲍比
....比利


编辑:下面是@Wrikken 的评论,为便于阅读而转载:

确实关于它。恕我直言,为每个关系添加一个从到到的日期(可能为 NULL 表示没有结束)。会发生离婚,收养等也会发生。另外:我会在addRelation()函数中添加一个反向类型和“ping-back”:

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);
    }
}
于 2010-07-21T23:40:39.227 回答
3

GEDCOM是用于在不同家谱软件之间交换家谱数据的开放规范。GEDCOM 文件是纯文本(通常是 ANSEL 或 ASCII),其中包含有关个人的家谱信息,以及将这些记录链接在一起的元数据。大多数家谱软件支持从 GEDCOM 格式导入和/或导出为 GEDCOM 格式。

使用 GEDCOM 的一个主要优势是,您可以使用Aldfaer(仅限荷兰语)GrampsLegacy Family Tree等桌面程序以及Genanet等在线工具来构建或修改您的家谱,并将其与他人的家谱进行比较.

使用 GEDCOM 格式的另一个主要优点是,您可以使用多种编程语言的库来保存和加载数据。PHP 库的示例包括GEDCOM Import/Export-FilterGenealogyGedcomPHP 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 数据模型的数据库。

于 2015-07-03T12:13:48.410 回答