page
有多个元素,并使用page_to_elements
表进行链接。每个element
都有多个element_fields
,并使用element_to_element_fields
进行关联。每个element_field
都有一个类型,并使用element_to_element_fields
表进行链接。元素中每个element_field
的值都有一个存储在element_values
表中的值(在value_char,value_text或value_num中为eitehr)。
以下是数据库结构:
pages:
id|name
elements:
id|name
element_fields_types (sql_type can be char, text or num):
id|name|sql_type
element_fields (names can be title, intro, content, link, number, etc etc):
id:element_field_type_id|name
element_to_element_fields:
id|element_id|element_field_id
page_to_elements:
id|page_id|element_id
element_values:
id|page_id|element_id|page_to_element_id|element_field_id|value_char|value_text|value_num
我正在寻找的是一个很好的hasManyToMany
解决方案,可以在我请求页面ID时获取所有值。我现在有多个循环和数组创建来获得这样的结构(其中的值来自正确的列名称,基于element_fields
中设置的内容):
$page = array(
'elements' => array(
[0] => array(
'element_name_here' => array(
'fields' => array(
[0] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
[1] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
[2] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
)
)
),
[1] => array(
'element_name_here' => array(
'fields' => array(
[0] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
[1] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
[2] => array(
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value',
'field_name_here' => 'Field value'
),
)
)
),
)
);
所以我需要类似下面的内容来生成上面的数组:
$page = Page::find($id);
print_r($page->getValues->toArray());
我对belongsToMany或hasManyToMany有一些经验,但从来没有这么深。
非常感谢任何帮助。
答案 0 :(得分:1)
您的架构非常复杂,但我相信您可以通过急切加载关系和利用收集方法来实现您想要的结构。
<?php
class Page extends Eloquent
{
public function elements()
{
return $this->belongsToMany(Element::class, 'page_to_elements');
}
public function values()
{
return $this->hasMany(Value::class);
}
public function getValues()
{
return $this->values()
// Eager-load the value element, the value field and its type
->with(['element', 'field.type'])->get()
// Group all the values by page element
->groupBy('page_to_element_id')->values()
// Group the values of each page element by the element name
->groupBy(function ($values) {
return $values->first()->element->name;
})
// Iterate each page element
->map(function ($values, $element) {
// Make an array with the element name as key and its fields as value
return [
$element => [
// Group the values by element field
'fields' => $values->groupBy('element_field_id')->values()
// Make an array with the field names and values for each element field
->map(function ($values) {
return $values->pluck('value', 'field.name')->all();
})->all(),
],
];
})->all();
}
}
class Element extends Eloquent
{
public function pages()
{
return $this->belongsToMany(Page::class, 'page_to_elements');
}
public function fields()
{
return $this->belongsToMany(Field::class, 'element_to_element_fields');
}
public function values()
{
return $this->hasMany(Value::class);
}
}
class Field extends Eloquent
{
public function type()
{
return $this->belongsTo(Type::class);
}
public function values()
{
return $this->hasMany(Value::class);
}
}
class Type extends Eloquent
{
public function fields()
{
return $this->hasMany(Field::class);
}
}
class Value extends Eloquent
{
public function page()
{
return $this->belongsTo(Page::class);
}
public function element()
{
return $this->belongsTo(Element::class);
}
public function field()
{
return $this->belongsTo(Field::class);
}
public function getValueAttribute()
{
$type = $this->field->type->sql_type;
return $this->getAttribute('value_'.$type);
}
}