如何建模此上下文以便创建自定义问题并收集答案?

How to model this context so its possible to create custom questions and collect answers?

上下文:

当用户(会议创建者)创建会议时,他可以为该会议创建注册表。因此,他访问页面“http://proj.test/conference/edit/1/questions”以编辑 ID 为 1 的会议的表单。

在此页面中,他可以通过复选框将现有问题与每个注册类型相关联。他还可以单击 "Add custom questions" 向表单中添加更多自定义问题。

例如,他可以创建一个自定义问题 "Whats your phone number?",然后可以将该问题关联到注册类型 "General" 或他之前创建的任何其他所有注册类型。

因此,当会议创建者访问“http://proj.test/conference/edit/1/questions/create”时,他可以访问一个表单来为 ID 为 1 的会议创建新的自定义问题。

在此表单中,用户(会议创建者)需要 select 问题的标题(例如:Phone 数字)和问题类型(例如:文本),然后单击在 "Store Question" 上。

问题字段的类型是一个 select 菜单,有 5 个选项(文本、长文本、单选按钮、select 菜单和复选框)。 如果用户 select 将问题类型设置为单选按钮、select 菜单或复选框,它会显示一些文本输入,以便用户可以为每个选项插入值。

然后在前端,当用户进行注册时,例如用户 John 与 2 个参与者进行注册,他和 Jake,注册类型为 "Rt 001",因此他需要填写表格,在这种情况下,他需要填写每个参与者的字段,因为会议创建者 select 编辑了选项 "collect info from all participants"。注册表总是询问进行注册的用户的姓名和电子邮件,但在这种情况下,注册表还要求用户提供 "what is your phone number",因为会议创建者创建的这个字段已被会议创建者关联到用户正在注册的注册类型 (Rt 001):

疑问:

我对如何根据表、列和关系来组织此上下文以正确建模这部分有一些疑问:

//会议模型

class Conference extends Model
{

     // A conference has many registration types
     public function registrationTypes(){
        return $this->hasMany('App\RegistrationType', 'conference_id');
     }
    // A conference can have  many questions
    public function questions(){
        return $this->hasMany('App\Question', 'conference');
    }

     // A conference has one organizer
     public function organizer(){
    return $this->belongsTo('App\User', 'user_id');
    }
}

注册类型型号:

class RegistrationType extends Model
{
    public function conference(){
        return $this->belongsTo('App\Conference');
    }

    // A registration type has many questions
    public function questions(){
        return $this->hasMany('App\Question', 'registration_type_id');
    }
}

//问题模型

class Question extends Model
{
    public function conference(){
        return $this->belongsTo('App\Conference');
    }
    public function registration_type(){
      return $this->belongsTo('App\RegistrationType');
    }

}

DB 图表,它不完整并且可能不正确地对此上下文建模,但显示了我现在拥有的图像图表:http://ibb.co/gVYVJS

如果我对你的问题的理解正确,你需要一个枢轴 table 将问题与多种注册类型相关联(无需复制)。

这个 table 可以命名为 registration_type_question 并且有两列:
registration_type_id(从 questions 移动),question_id

现在 RegistrationTypeQuestion 之间存在 BelongsToMany 关系:

class RegistrationType extends Model
{
    public function questions(){
        return $this->belongsToMany('App\Question', 'registration_type_question');
    }
}

根据我从问题和讨论中获得的信息,我对架构进行了更改。注意:在此模式中,我使用 laravel(默认情况下)使用的命名标准。像复数 table 名称,主键将是 'id' 等

大部分与问题中的架构相似。我稍微解释一下,

  • users - 会议创建者table。
  • conferences - 会议,created_user_id 是创建它的用户。
  • registration_types - 保存注册类型和 conference_id link 它所属的会议。
  • questions - 持有 conference_id 的问题显示属于哪个会议问题,
  • registration_types 枢轴 table 保存注册类型到问题的映射。
  • registrations - table 包含注册信息。
  • participants - 保存带有姓名和电子邮件字段的参与者条目。每个参与者将有单独的 registration_type.
  • answers - 包含每个参与者给出的答案。它有 question_id 表示哪个问题和 participant_id 表示它属于哪个参与者。

以上架构为每种注册类型添加了required选项,这样您就可以将问题在一种类型中设置为必填项,而在另一种类型中不设置为必填项。必填字段作为 extra attribute 添加到 registration_type_questions 枢轴 table.

根据注册类型查找问题

class RegistrationType extends Model
{
    public function questions(){
        return $this->belongsToMany(App\Question::class, 'registration_type_questions');
    }
}

$registration_type->questions->withPivot('required');

正在添加参与者对问题的回答。

class Answer extends Model
{
    public function question(){
        return $this->belongsTo(App\Question::class);
    }
    public function participant(){
        return $this->belongsTo(App\Participant::class);
    }
}

Answer::create([
   'participant_id' => $participant_id,
   'question_id' => $question_id,
   'answer' => 'answer'
])

conference_idquestions中的用法table

conference_id开会属于哪个问题。这将有助于在 edit/create 会议页面中显示已创建的问题。

如何处理用户注册,

only_for_registration 标志用于给定会议创建页面的 'Only from the user that holds registration' 选项。如果是 false,您将不会向额外的参与者显示姓名和电子邮件字段。

例子

为了更清楚,让我看一下你给出的例子。

  1. 会议创建者"Jake"在系统上创建一个帐户。

    • 我们将在用户 table 中创建一个包含必要帐户字段的条目。
  2. "Jake" 创建一个新会议并 select 编辑 "All Participants" 选项。

    • 在会议 table 中创建一个新条目,名称和 only_for_registration 标志设置为 false(因为 Jake 选择 "All Participants")。
  3. "Jake" 为 "rt 1" 和 "rt 2".

    创建两个注册类型
    • registration_types table 中使用 conference_id(来自第 2 步)和名称创建两个条目。 "rt 1" 与 id 1 和 "rt 2" 与 id 2.
  4. "Jake" 创建问题 "Whats your phone number?" 类型为文本。

    • questions table 中创建一个条目,其中包含问题文本和 "conference_id" 作为第 2 步中的 ID。现在,您可以使用 Questions::where("confrence_id", $current_confrence_id)->get() 在会议编辑页面中显示问题。那就是confrence_id在问题table.
    • 中的用法
  5. "Jake" 仅将 "Whats your phone number?" 问题与 "rt 2".

    相关联
    • registration_type_questions 中添加条目 'question_id' 1(来自步骤 4),registration_type_id 2(来自 "rt 2" 的步骤 3)。如果 "Jake" 是 selected 问题是强制性的,您可以将 required 标志设置为真。
  6. 在前端"John"来到注册页面,点击"Register"。

  7. "John" select 2 "rt 1" 名参与者和 2 "rt 2" 名参与者并单击 "Next"。

    • 由于我们来自会议页面,我们已经有 conference_id,使用 $conference->registrationTypes oneToMany 关系获取所有 registration_types
    • 一旦约翰按下 "Next",您可以将此信息保存在 session 或 front-end 本身中。由于未提供用户信息,因此在此阶段无需提交数据库。
  8. "John" 看到填写 4 个用户条目的表单,所有条目都有姓名和电子邮件字段,还有 2 个条目有额外的 "Whats your phone number?" 问题。

    • 默认情况下仅显示第一个条目的姓名和电子邮件,但由于 only_for_registration 标志为假,因此显示所有条目的姓名和电子邮件字段。
    • 对于每个条目,使用 $registation_type->questions 关系获取问题。因此,由于只有 2 个条目具有 "rt 2",我们将只显示 "Whats your phone number?" 到 2 个字段并隐藏 question_id 字段。
    • 可选,对于所有条目,让用户在他selected 的注册类型之间切换。这样他就可以灵活地选择第一个参与者,即他自己是rt2。
  9. "John" 填写所有问题的答案并点击 "Next"。

    • 在 "registration" table 中创建条目。
    • 遍历第 8 步中的所有条目。
      • 使用步骤 8 中的 registration_id、registration_type 值以及电子邮件和姓名在参与者 table 中创建一个条目。当其他用户不需要时,将电子邮件和姓名保留为空。
      • 如果问题是一个自定义问题,在答案 table 中创建一个条目,其中包含最后一点的参与者 ID 和隐藏的 question_id 字段。

如果 only_for_registration 标志为真,即 "Jake" selected "Only from the user that does the registration",那么您只能向第一个条目显示电子邮件和姓名字段。