0

疑似ディレクトリシステムを表すmysqlテーブルがあります。

CREATE TABLE `file_directories` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `parent_id` int(11) DEFAULT NULL,
 `name` varchar(255) NOT NULL,
 `level` int(11) NOT NULL DEFAULT '1',
 `created` datetime NOT NULL,
 PRIMARY KEY (`name`,`id`),
 KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

ユーザーがこのシステムを閲覧しているとき、私たちの関数は列からのエントリで構成されるパスを受け取りnameます。

したがって、first/child of first/grandchildまたはのようなものsecond/child of second/grandchildが有効なパスであり、データベースでは次のようになります。

/----------------------------------------------------\
| id | parent_id | name            | level | created |
|----|-----------|-----------------|-------|---------|
| 1  | NULL      | First           | 1     | ...     |
| 2  | 1         | Child of First  | 2     | ...     |
| 3  | 2         | Grandchild      | 3     | ...     |
| 4  | NULL      | Second          | 1     | ...     |
| 5  | 4         | Child of Second | 2     | ...     |
| 6  | 5         | Grandchild      | 3     | ...     |
\----------------------------------------------------/

現在、ディレクトリの子を一覧表示する場合、私のプロセスは次のとおりです。

$path = 'first/child of first'; // demo data
$path = explode('/', $path); //array('first', 'child of first');
$level = count($path);
$name = end($path);

//query is not actually built like this, it uses the Codeigniter Active Records library
//but this is effectively the end result,
$sql = "SELECT * FROM `file_directories` WHERE `name` = '$name' AND `level` = $level";

///etc

grandchild同じ名前で同じレベルに存在するディレクトリを処理するまでは、これは問題なく機能します。

ディレクトリ構造は、1つのディレクトリのみが同じで存在できることを強制しますが、異なる'dディレクトリが同じparent_idに存在する可能性があります。namenameparent_idlevel

渡されるデータを変更できないため、これを行うために考えられる唯一の方法は、ルートノードから開始し、複数のクエリをループダウンして正しい子を見つけることです。

したがって、2番目の孫の場合、クエリは次のようになります。

$parent_id = NULL;
foreach($path as $seg){
    $id = SQL: SELECT `id` FROM `file_directories` WHERE `name` = '$seg' AND `parent_id` = (IS NULL for root node) $parent_id;
}

//Get the actual node
$node = SQL: SELECT `*` FROM `file_directories` WHERE `id` = '$id';

しかし、それは多くのクエリなので、与えられたデータを変更せずに、ツリーをトレースするためのより良い方法はありますか?または正しいノードを選択しますか?

4

1 に答える 1

1

再帰関数の不思議について学びましょう: このコードは少し単純化されています。

function select_child($node_id, $level, $target_level) {
  if(SELECT new_node_id WHERE parent_id = $node_id)
    if($level = $target_level) {
      return($new_node);
    } else {
      $results->add(select_child($new_node_id, ($level +1), $target_level);
    }
  } else {
    return(NULL);
  }
}

この関数は、「リーフ」(子のないノード) が見つかるか、ターゲット レベルに到達するまで、指定されたノードの子をループします。ツリーを操作している場合、ほとんどの関数は再帰的でなければなりません (指定された条件が一致するまで自分自身を呼び出します)。

于 2013-01-27T13:09:21.170 に答える