Laravel数据库模型中页面的深层链接值

时间:2017-02-18 15:55:32

标签: php mysql laravel laravel-5.1

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有一些经验,但从来没有这么深。

非常感谢任何帮助。

1 个答案:

答案 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);
    }
}