我正在开发一个允许我存储嵌套标签和类别的数据库,并且很难找到一种相对简单的查询方式。我正在使用Laravel,因此进一步的障碍是确保它以合理的方式与Eloquent兼容。
目前,我尝试了两种方式。
第一种方法是使用一个名为entities
的表,其中type
列设置为tag
或category
。这似乎与使用的数据结构相当好,但是查询有点不愉快。
第二种方式是有两个表,每种类型一个。这是一个完整的噩梦,因为这两个表都需要有两个父列,并且无法使用合理的代码进行查询。
所以,我假设第一种方式是正确的方式。 是否有一种合理的方式来安排模型和数据库迁移?如何准确查询数据库?这是我的模型(文件是指被标记的文件):
class Entity extends Model
{
public function children() {
return $this->hasMany('App\Entity');
}
public function parent() {
return $this->belongsTo('App\Entity');
}
public function files() {
return $this->belongsToMany('App\File')->withTimestamps();
}
}
我的迁移(order
是一个列,确保标记和类别显示在正确的位置,如果兄弟姐妹。它还应该允许我在前端使用JavaScript重新排列它们,我还没有研究过正确地说):
Schema::create('entities', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('order');
$table->enum('type', ['tag', 'category']);
$table->string('name');
$table->string('title');
$table->text('description')->nullable();
$table->integer('entity_id')->unsigned()->nullable();
$table->timestamps();
$table->foreign('entity_id')->references('id')->on('entities');
});
这是前端使用的数据结构的一个工作示例,我需要从数据库生成:
[
{
"__type": "Tag",
"id": "water",
"name": "Water",
"description": "Containing water of any kind.",
"checked": false,
"children": [
{
"__type": "Tag",
"id": "salt_water",
"name": "Salt Water",
"description": "Salt Water, for example in the Ocean.",
"checked": false,
"children": []
},
{
"__type": "Category",
"id": "fresh_water",
"name": "Fresh Water",
"description": "Fresh Water, such as rivers and lakes.",
"children": [
{
"__type": "Tag",
"id": "river",
"name": "River",
"description": "A river of water.",
"checked": true,
"children": []
},
{
"__type": "Tag",
"id": "lake",
"name": "Lake",
"description": "A lake of water.",
"checked": false,
"children": []
}
]
}
]
},
{
"__type": "Category",
"id": "species",
"name": "Species",
"description": "The Species of creature.",
"featured": true,
"children": [
{
"__type": "Tag",
"id": "dog",
"name": "Dog",
"description": "Canis Familiaris.",
"checked": false,
"children": []
},
{
"__type": "Tag",
"id": "cat",
"name": "Cat",
"description": "Felis Catus.",
"checked": false,
"children": [
{
"__type": "Tag",
"id": "tiger",
"name": "Tiger",
"description": "A tiger.",
"checked": false,
"children": []
}
]
}
]
}
]
答案 0 :(得分:0)
如果你的数据已经在PHP数组中,你可以使用其中一个递归函数
function getChecked($root)
{
$output = [];
if(!is_array($root) && !isset($root['children']))
{
$root = array($root);
}
foreach($root as $item)
{
if(isset($item['checked']) && $item['checked']) {
if(isset($item['children']))
{
$children = getChecked($item['children']);
$item['children'] = $children;
}
$output[] = $item;
}
}
return $output;
}
function getChecked_lazy($root)
{
$output = [];
if(!is_array($root) && !isset($root['children']))
{
$root = array($root);
}
foreach($root as $item)
{
if(isset($item['children']))
{
$children = getChecked_lazy($item['children']);
$item['children'] = $children;
}
if( (isset($item['checked']) && $item['checked']) || isset($item['children']) && !empty($item['children']))
{
$output[] = $item;
}
}
return $output;
}
$data = [
[
"id" => "dog",
"checked" => true,
"children" => [
[
"id" => "wolf",
"checked" => true,
],
[
"id" => "fox",
"checked" => false
],
]
],
[
"id" => "cat",
"checked" => false,
"children" => [
[
"id" => "lion",
"checked" => true
],
],
],
];
echo json_encode(getChecked($data), JSON_PRETTY_PRINT);
echo "\n";
echo json_encode(getChecked_lazy($data), JSON_PRETTY_PRINT);
输出:
[ { "id": "dog", "checked": true, "children": [ { "id": "wolf", "checked": true } ] } ] [ { "id": "dog", "checked": true, "children": [ { "id": "wolf", "checked": true } ] }, { "id": "cat", "checked": false, "children": [ { "id": "lion", "checked": true } ] } ]
或者您可以通过SQL查询checked = true,然后尝试查找根(其中parent为null)。
或其他方式