我想会有一种方法可以同时获取目标和目标(或整个数据对象,等等)的 id,并检查目标是否在目标路径中。如果是,则该方法将返回 false 或抛出异常,否则将返回 true。该方法可以作为控制结构引入到您的目录复制代码流中。
就个人而言,对于分层数据结构,我会将其实现为嵌套 set。设置和修复嵌套集可能很麻烦,但我发现检查节点之间的关系和获取整个子树非常方便。
这是一个 PHPUnit 测试,它对我的想法进行了部分且有些幼稚的实现:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(-1);
require 'vendor/autoload.php';
class ParentingSucks
{
public $data = array();
public function isAllowed($targetId, $destId)
{
$target = $this->getById($targetId);
$dest = $this->getById($destId);
$parent = $this->getById($dest['childOf']);
$isAllowed = true;
while ($parent) {
if ($parent['id'] == $targetId) {
$isAllowed = false;
break;
}
$parent = $this->getById($parent['childOf']);
}
return $isAllowed;
}
public function getById($id)
{
if (isset($this->data[$id])) {
return $this->data[$id];
}
return array();
}
}
class HowIMetYourParentDir extends PHPUnit_Framework_TestCase
{
/**
* @test
* @dataProvider generate
*/
public function droppingOnParentNotAllowed($data, $target, $dest, $outcome)
{
$stub = $this->getMock('ParentingSucks', null);
$stub->data = $data;
$result = $stub->isAllowed($target, $dest);
$this->assertEquals($result, $outcome, 'Oh no!');
}
public function generate()
{
$fakeData = array(
1 => array('id' => 1, 'name' => 'A', 'childOf' => 0),
2 => array('id' => 2, 'name' => 'B', 'childOf' => 1),
3 => array('id' => 3, 'name' => 'C', 'childOf' => 0),
4 => array('id' => 4, 'name' => 'D', 'childOf' => 3),
5 => array('id' => 5, 'name' => 'E', 'childOf' => 2),
6 => array('id' => 6, 'name' => 'F', 'childOf' => 5),
);
return array(
array(
$fakeData,
2, // target
6, // dest
false, // outcome
),
array(
$fakeData,
4,
2,
true,
),
array(
$fakeData,
4,
2,
true,
),
array(
$fakeData,
3,
4,
false,
),
);
}
} false, // outcome
),
array(
$fakeData,
4,
2,
true,
),
array(
$fakeData,
4,
2,
true,
),
array(
$fakeData,
3,
4,
false,
),
);
}
}
变量/函数/类名称可能不适合您的域模型,所以不要介意它们。