【问题标题】:Relationship Design关系设计
【发布时间】:2015-06-18 14:00:21
【问题描述】:

我正在构建一个应用程序,客户可以在其中从预定义的模板创建文档,使用自己的文本编辑一些字段并保存它。我已经按照我的想法勾勒出了关系,转换成 Laravel 基本没问题:

我唯一的问题是如何处理 FieldValue 关系。这个想法是模板定义了所有字段,而不是在每个文档上重新创建这些字段,它应该只在其模板中查找它们。这意味着 FieldValue 需要查找它的 Document、它的 Template 并从那里找到相应的 Field。

有没有一种简洁的方法来实现这一点,或者有更好的方法来设计关系以使其更实用?

【问题讨论】:

    标签: php laravel database-design laravel-5 relationship


    【解决方案1】:

    按照您的图表,看起来像一个带有数据透视表的数据透视表...

    在 Laravel 中通常会这样建模:

    class Document extends Model
    {
        public function template()
        {
            return $this->belongsTo('App\Template');
        }
    
        public function fields()
        {
            return $this->belongsToMany('App\Field')->withPivot('value');
        }
    }
    
    class Template extends Model
    {
        public function organisation()
        {
            return $this->belongsTo('App\Organisation');
        }
    
        public function documents()
        {
            return $this->hasMany('App\Document');
        }
    
        public function fields()
        {
            return $this->hasManyThrough('App\Field', 'App\Section');
        }
    
        public function sections()
        {
            return $this->hasMany('App\Section');
        }
    }
    
    class Section extends Model
    {
        public function fields()
        {
            return $this->hasMany('App\Document')->withPivot('value');
        }
    
        public function template()
        {
            return $this->belongsTo('App\Template');
        }
    }
    
    class Field extends Model
    {
        public function documents()
        {
            return $this->belongsToMany('App\Document')->withPivot('value');
        }
    
        public function section()
        {
            return $this->belongsTo('App\Section');
        }
    }
    
    class Organisation extends Model
    {
        public function documents()
        {
            return $this->hasManyThrough('App\Document', 'App\Template');
        }
    
        public function templates()
        {
            return $this->hasMany('App\Template');
        }
    }
    

    使用相关表(如果坚持使用 laravel 默认值):

    fields
        id - integer
        section_id - integer
    
    documents
        id - integer
        template_id - integer
    
    templates
        id - integer
        organisation_id - integer
    
    sections
        id - integer
        template_id - integer
    
    organisations
        id - integer
    
    document_field
        id - integer
        document_id - integer
        field_id - integer
        value - string
    

    然后您可以通过多种不同的方式访问事物。这是一个例子:

    $user = App\User::find(3);
    
    $organisation = $user->organisation;
    
    foreach ($organisation->documents as $document)
    {
        foreach ($document->fields as $field)
        {
            echo $field->pivot->value;
        }
    }
    

    并插入:

    $field = App\Field::find(2);
    
    $document = App\Document::find(4);
    
    $value = 'My field value';
    
    $document->fields()->save($field, ['value' => $value]);
    

    相关文档:

    【讨论】:

    • 我给这个答案接受 + 100 赏金;我实际上使用了 Arjan 的部分答案(合并模板和部分,并将格式组合到一个表中),但这个答案对我遇到的主要问题更有帮助
    【解决方案2】:

    希望这就是你的意思:

    $doc = Document::findOrFail(Input::get('docId'));
    $sections = $doc->template->sections;
    $fieldValues = $doc->field values;
    

    现在您只需在字段值上运行并获取字段和部分并开始放置内容。

    为了获得更好的性能,我希望加载 fieldValue 参数:

    ->with('field');
    

    【讨论】:

    • 您是否建议手动迭代字段和字段值以根据键名匹配它们(可能在文档的实例化代码中完成)?如果是这样,我希望找出某种结构方式,以便更有机地发生 - 如果没有,你能澄清一下吗? :-)
    • 我的意思是你可以遍历 fieldValue 并且对于每一个你可以很容易地获得字段和部分。
    【解决方案3】:

    回答你的第一个问题:

    我建议你称它为 content。您可以像现在一样处理内容。目前的关系已经足够好了。您必须将其与其他表分开。

    第二个问题:更好的方法

    我根据您的 ERD 自己创建了一个 ERD:

    我改变了一些想法。

    1. 不是那么重要,但文档来自用户。
    2. 模板可以有子模板。这样做的结果是您可以重用子模板。例如。如果您有徽标,则每次都可以将其放入您的文档中。
    3. 由于有了新的模板表,您不再需要部分。使用新方法,您可以定义子部分/模板。
    4. 属性都放在一个表中。使用这种方法,您可以为字段定义无限属性。这可以更灵活地分配。这些被引用到一个字段和内容。但是不需要 content_id。我刚刚把它放在那里,这样你就可以很容易地检查它适用于哪个字段。
    5. 您问题的重点是字段值/内容。内容参考文档。您可以从文档中填写模板的字段。

    我希望这对你来说很清楚。我看到的优点是:

    1. 属性更灵活
    2. 内容查找很简单,并且可以引用到字段

    我没有更改内容表上的任何内容。保持原样。这样就好了!希望这对您有所帮助。如果你使用Schema designer,你可以很容易地找回你的模型!

    【讨论】:

    • 我接受并将 100 赏金奖励给 fungku,因为他的答案更清楚一点,但我打算开始另一个 50rep 赏金奖励你的答案,因为你提出的几点非常有用;特别指出模板和部分可以合并在一起,格式化方法也可以。不幸的是,我必须将我奖励的任何后续赏金加倍,所以我没有创建 200 代表的赏金。不过,如果有什么好处的话,我要谢谢你:-)
    • 我可以处理它 :) 我希望我的建议是有帮助的。
    猜你喜欢
    • 2019-07-18
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多