Pedigree/Family tree chart from database

2019-04-18 01:20发布

问题:

I am trying to generate pedigree (in other words family tree :) ) table from database...

My schema:

CREATE TABLE `horses` ( 
`horse_id` int(10) NOT NULL AUTO_INCREMENT,
`horse_name` varchar(32) NOT NULL,
`horse_sire` int(10) DEFAULT NULL,
`horse_dam` int(10) DEFAULT NULL, 
PRIMARY KEY (`horse_id`),
KEY `FKsire` (`horse_sire`),
KEY `FKdam` (`horse_dam`),
CONSTRAINT `FKdam` FOREIGN KEY (`horse_dam`) REFERENCES `horses` (`horse_id`),
CONSTRAINT `FKsire` FOREIGN KEY (`horse_sire`) REFERENCES `horses` (`horse_id`)
)

p.s. 'horse_dam' and 'horse_sire' represents parents... I have spent days on this problem, searching, experimenting... And currently I have this partly solution:

display_children($selected_horse_id, 5);

        function display_children($parent, $level) {
            mysql_connect('localhost','root','');
            mysql_select_db('hdb');
            $result = mysql_query('SELECT * FROM horses WHERE horse_id="'.$parent.'";');


            while ($row = mysql_fetch_array($result)) {

                echo "<tr><td>";
                echo $row['horse_name'];
                echo "</td></tr>";

                display_children($row['horse_dam'], $level+1);
                display_children($row['horse_sire'],$level+1);
            }
        }

which generates table in one row :( I cannot think of proper way to implement it... And the result I want is Pedigree Query

Any help or hint is highly appreciated :), Thanks in advance

回答1:

I have already resolved problem few month ago... I'm posting answer, so this might be helpful for other fellow developers... p.s. The project was written in Yii 1.1

Firstly, in my HorseController assigned private array type variable where I am going to keep Pedigree:

private $horses = array();

Then, I wrote function that will get all nodes (parents) from database:

public function getParents($id)
{
    global $horses;
    $horses[] = Horses::model()->findByPk($id)->horse_id;
    if($this->loadModel($id)->horse_sire != null && $this->loadModel($id)->horse_dam != null)
    {
        $this->getParents($this->loadModel($id)->horse_sire);
        $this->getParents($this->loadModel($id)->horse_dam);
    }
    return $horses;
}

Then, I modified ActionView function, where all nodes from database will be passed to View

public function actionView($id)
{
    $this->horses = $this->getParents($id);
    $this->render('view',array(
        'model'=>$this->loadModel($id),
        'parents'=>$this->horses,
    ));
}

And finally a bit of UGLY CODE that will show pedigree (like this Pedigree Query) :)

<table>
            <?php
                $reverse_multiplier = (count($parents)+1)/2;
                $last_node_count = 0;
                for($i = 0; $i < count($parents); $i++)
                {
                    if($i == 0 && $last_node_count ==1)
                        echo "<tr>";

                    echo "<td rowspan='$reverse_multiplier'>";

                    echo "<a href=".Yii::app()->baseUrl."/index.php/horses/".Horses::model()->model()->findByPk($parents[$i])->horse_id." >";
                    echo Horses::model()->model()->findByPk($parents[$i])->horse_name;
                    echo "</a>";
                    echo "<br/>";
                    echo Horses::model()->model()->findByPk($parents[$i])->horse_yob;

                    echo "</td>";
                    if($reverse_multiplier == 1 || $reverse_multiplier == 0.5)
                        echo "</tr>";

                    if($reverse_multiplier == 0.5 && $last_node_count <= (count($parents)+1)/4)
                        $reverse_multiplier = (count($parents)+1)/8;
                    else
                        $reverse_multiplier = $reverse_multiplier/2;

                    if($last_node_count == (count($parents)+1)/4)
                    {
                        $reverse_multiplier = (count($parents)+1)/4;
                        $last_node_count=0;
                    }
                    if($reverse_multiplier == 0.5 || $reverse_multiplier == 1)
                        $last_node_count++;
                }
            ?>
        </table>

And that's it :) Hope it was helpful...