【问题标题】:PHP Calculate Number of downline in binary treePHP计算二叉树中的下线数
【发布时间】:2014-08-16 15:57:47
【问题描述】:

为了计算二叉树中的下线数量,我正在尝试以下脚本,方法是创建 2 个数据库用于注册和成员下线结构。它确实有效。

但是成员结构数据库增长非常快。导致二叉树中的 n 级将生成 n 条记录用于单用户注册。我只是想知道如果用户在 1000 级注册,那么它将在单用户注册中创建 1000 条记录。

此系统还有其他解决方案吗?

完整的长脚本是:

CREATE TABLE IF NOT EXISTS `member` (
  `id` int(255) NOT NULL AUTO_INCREMENT,
  `username` varchar(55) CHARACTER SET utf8 NOT NULL,
  `upline` varchar(55) CHARACTER SET utf8 NOT NULL,
  `position` varchar(10) NOT NULL,
  `sponsor` varchar(55) CHARACTER SET utf8 NOT NULL,
  `_left` varchar(55) CHARACTER SET utf8 NOT NULL,
  `_right` varchar(55) CHARACTER SET utf8 NOT NULL,

  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

制作下线结构表:

CREATE TABLE IF NOT EXISTS `net_downline` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(60) NOT NULL,
  `upline` varchar(60) NOT NULL,
  `level` int(7) NOT NULL,
  `position` varchar(10) NOT NULL,

  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;

从简单或基本的注册表中获得:

$newuser        = htmlentities(trim($_POST['user']));
$sponsor        = htmlentities(trim($_POST['sponsor']));    
$upline         = htmlentities(trim($_POST['upline']));
$position       = htmlentities(trim($_POST['position']));

在注册过程中,执行此树步骤:

// 1. register new member
$users->dummyRegister($newuser, $sponsor, $upline, $position);
// 2. update upline
$users->dummyUpdateUpline($newuser, $upline, $position);

// 3. create donwline structure of binary tree
$level=0;
$memberid=$newuser;
do{
$getdata=$users->dummyGetUpline($memberid); 
$uplne=$getdata[2]; 
$posi=$getdata[3];

$level++;
if($uplne!==''){
$users->dummyInsert_NetDownline($newuser, $uplne, $posi, $level);
}
$memberid=$uplne;
}
while($memberid!='');

该脚本的“用户”类:

<?php  // start class

    class Users{

        private $db;
        public function __construct($database) {
            $this->db = $database;
        }   
    public function dummyRegister($username, $sponsor, $upline, $position, $today){

            $query  = $this->db->prepare("INSERT INTO `member` (`username`, `sponsor`, `upline`, `position`, `entry_date` ) VALUES (?, ?, ?, ?, ?) ");          
            $query->bindValue(1, $username);
            $query->bindValue(2, $sponsor);
            $query->bindValue(3, $upline);
            $query->bindValue(4, $position);
            $query->bindValue(5, $today);

            try{
                $query->execute();
             }catch(PDOException $e){
                die($e->getMessage());
            }   
        }


    public function dummyUpdateUpline($username, $upline, $position){

            if ($position=='left') {
            $query  = $this->db->prepare("UPDATE `member` SET `_left`=? WHERE username=? ");
            }elseif ($position=='right') {
            $query  = $this->db->prepare("UPDATE `member` SET `_right`=? WHERE username=? ");
            }

            $query->bindValue(1, $username);
            $query->bindValue(2, $upline);

            try{
                $query->execute();

            }catch(PDOException $e){
                die($e->getMessage());
            }   
        }

    public function dummyGetUpline($newuser) {// for demo

            $query = $this->db->prepare("SELECT * FROM `member` WHERE `username`= ?");
            $query->bindValue(1, $newuser);

            try{
                $query->execute();
                $rows = $query->fetch();

                return $rows;//['upline'];

            } catch(PDOException $e){
                die($e->getMessage());
            }
        }

    public function dummyInsert_NetDownline($newuser, $upline, $posi, $level){// for demo

            $query  = $this->db->prepare("INSERT INTO `net_downline` (`username`, `upline`, `position`, `level` ) VALUES (?, ?, ? ,?) ");
            $query->bindValue(1, $newuser);
            $query->bindValue(2, $upline);
            $query->bindValue(3, $posi);
            $query->bindValue(4, $level);

            try{
                $query->execute();

            }catch(PDOException $e){
                die($e->getMessage());
            }   
        }   

    }// endclass

创建initial.php并放在顶部regitration php脚本:

<?php  
if(!isset($_SESSION)) { session_start(); }
require 'conn/database.php'; // in folder conn
require 'clas/users.php';   // in folder class
$users      = new Users($db);
} 
?>

这个处理数据库连接(clas/database.php 脚本):

<?php 
$config = array(
    'host'      => 'localhost',
    'username'  => 'root',
    'password'  => '',
    'dbname'    => 'sampledatabase'
);

$db = new PDO('mysql:host=' . $config['host'] . ';dbname=' . $config['dbname'], $config['username'], $config['password']);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  

【问题讨论】:

  • 在关系数据库中处理树并不像在应用程序中那么简单。在常识中,adjanced-tree 是一种设计反模式
  • 我建议您为此使用nested sets。使用 NS,计算到节点的路径将像 SELECT x WHERE x.left &lt; node.left AND x.right &gt; node.right 一样简单。
  • georg,你能写出使用NS的示例脚本吗?
  • @user3706926:啊,你已经在使用它了,对吧?那么,究竟是什么问题呢?
  • 我遇到了成员结构的数据库文件问题。规模越来越大。我认为这不是正常的乔治。难以处理大型用户。

标签: php mysql


【解决方案1】:

这是我尝试了很多方法后的答案。解决我之前的问题。只需使用上面的单个成员表。

显示下线数量,左右。我将此脚本插入到树 A 中的每个用户的 HTML 成员树页面中,一直到 B/C,一直到 D/E/F/G):

<?php echo $users->downline_number($member,'_left'); ?>
<?php echo $users->downline_number($member,'_right'); ?>

在用户类中添加此功能;

function downline_number($member,$position) {

$query  = $this->db->prepare("SELECT * FROM `member` WHERE `upline`='$member' AND `position`='$position'");
        $query->bindValue(1, $member);
        $query->bindValue(2, $position);

try{
        $query->execute();
        $rows = $query->fetch();

        if($this->count_downline($member,$position) >0 ){
        $total=$this->total_members_down($rows['username']);
        }else{
        $total=0;
        }

        return $total;      

        }catch(PDOException $e){
            die($e->getMessage());
        }   

    }   

function count_downline($member,$position) {

$query  = $this->db->prepare("SELECT * FROM `member` WHERE `upline`=? AND `position`=? ");
        $query->bindValue(1, $member);
        $query->bindValue(2, $position);
    try{
        $query->execute();
        return $rows = $query->rowCount();

        }catch(PDOException $e){
            die($e->getMessage());
        }   
    }   

function total_members_down($upline,$reset=0) {
global $num;
if ($reset==0) { $num=1; }

$query  = $this->db->prepare("SELECT * FROM `member` where `upline`='$upline' order by id asc");
        $query->bindValue(1, $upline);
try{

$query->execute();

if ($upline !='') {

            if ($this->total_down($upline) > 0 ) {
                    while ($rows = $query->fetch() ) {
                    $num++;
                    $this->total_members_down($rows['username'],$num);
                    } 
                    return $num;
            } else { 
            return $num;
            }
} else { $num=0; return $num;  }            

     }catch(PDOException $e){
            die($e->getMessage());
        }   
}   

function total_down($upline) {

$query  = $this->db->prepare("SELECT * FROM `member` where `upline`='$upline' order by id asc ");
        $query->bindValue(1, $upline);

    try{
        $query->execute();
        return $rows = $query->rowCount();

        }catch(PDOException $e){
            die($e->getMessage());
        }   
    }   

它可以显示二进制成员树结构。此处未附加显示memberID,原因很简单。只是左右下线号码。

希望这篇文章能帮助其他需要它的人。有什么更好的方法建议吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多