7

PHP で家系図を表現する方法を探しています。これは、子が2 つ(またはそれ以上) の親から継承する必要があることを意味します。

要件は次のとおりです。

  • 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

このように 1 回ですべてを行うことはできませんarray()。このようにツリーを設定できますが、複数の親やその他の関係を持つより複雑なグラフを設定するには、複数行のコードが必要です。

これにOOを投げると、大いに役立ちます。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のコメントを以下に示します。

それについては確かに。IMHOは、すべての関係に開始日を追加します(終了しない場合は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);
    }
}
于 2010-07-21T23:40:39.227 に答える
3

GEDCOMは、異なる系図ソフトウェア間で系図データを交換するためのオープン仕様です。GEDCOM ファイルはプレーン テキスト (通常は ANSEL または ASCII) で、個人に関する系図情報と、これらのレコードをリンクするメタ データが含まれています。ほとんどの家系図ソフトウェアは、GEDCOM フォーマットからのインポートおよび/または GEDCOM フォーマットへのエクスポートをサポートしています。

GEDCOM を使用する主な利点は、Aldfaer (オランダ語のみ)GrampsLegacy Family Treeなどのデスクトップ プログラムや、 Geneanetなどのオンライン ツールを使用して、自分の家系図を作成または変更し、他の家系図と比較できることです。 .

GEDCOM 形式を使用するもう 1 つの大きな利点は、データを保存およびロードするために自由に使用できる複数のプログラミング言語のライブラリがあることです。PHP ライブラリの例は、GEDCOM Import/Export-FilterGenealogyGedcomまたは PHP GEDCOMです。

PHP GEDCOM を使用すると、GEDCOM ファイルの読み取りと解析は次のように簡単になります。

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

GEDCOM を使用することの主な欠点は、GEDCOM のデータ形式が核家族を中心に構築されていることです。つまり、同性パートナーシップ、混合家族、同棲などの非伝統的な家族構造のサポートが制限されていることを意味します。この種の関係をサポートするために GEDCOM を拡張することは可能ですが、このような拡張では、異なるソフトウェア間の相互運用性が制限されます。

GEDCOM を使用することのもう 1 つの大きな欠点は、GEDCOM ファイルがモノリシックであることです。数千人のデータセットがある場合、またはデータ構造を頻繁に変更したい場合は、パフォーマンスの問題が発生する可能性があります。特にそのような場合は、代わりにデータベースにデータを保存することをお勧めします。それでも、GEDCOM が役に立たないというわけではありません。このような場合、データベースと GEDCOM 形式の間でインポート/エクスポートできる GEDCOM 形式に基づくデータベース スキーマの使用を検討することをお勧めします。このために、ライブラリも存在します。Oxy-Genがその例です。


GEDCOM に代わるものは、GenTech のデータ モデル またはGramps データ モデルです。GEDCOM 標準ほど一般的には使用されていませんが、ニーズにより適している場合があります。

Gramps データ モデルを使用する場合は、たとえば次のように使用できます。Gramps PHP エクスポーターを使用して、データを SQLite データベースにエクスポートします。Gramps データ モデルに適したデータベースを設計する方法については、このソースも参照してください。

于 2015-07-03T12:13:48.410 に答える