【问题标题】:How to create an optimized model, tables and the relationship between them?如何创建优化的模型、表以及它们之间的关系?
【发布时间】:2019-03-25 12:38:05
【问题描述】:

我有开发自定义项目,其中有数据库表:

  • 用户
  • 候选人
  • 公司
  • 范围
  • 技能

用户表:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('nickname')->unique();
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->boolean('type')->default(0); // 0 = candidate and 1 = company
    $table->rememberToken();
    $table->timestamps();
});

候选人表:

Schema::create('candidates', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade');
    $table->string('name')->nullable();
    $table->string('lastname')->nullable();
    $table->string('surname')->nullable();
    $table->text('about')->nullable();
    $table->timestamps();
});

公司表:

Schema::create('companies', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade');
    $table->unsignedInteger('logo');
    $table->foreign('logo')
          ->references('id')
          ->on('images')
          ->onDelete('cascade');
    $table->string('name')->nullable();
    $table->text('about')->nullable();
    $table->string('website')->nullable();
    $table->integer('employees')->nullable();
    $table->timestamps();
});

范围表:

Schema::create('scopes', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

技能表:

Schema::create('skills', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

在这里,任何用户类型都有范围和技能。我可以通过创建一个表来解决此解决方案:

属性表:

Schema::create('attributes', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade');
    $table->morphs('model');
    $table->timestamps();
});

属性表中的示例数据:

----------------------------------------
| id | user_id | model_id | model_type |
----------------------------------------
| 15 |   176   |  34458   | App\Scope  |
----------------------------------------
| 29 |   245   |  17654   | App\Skill  |
----------------------------------------

但是在这个解决方案中对我来说有一个不好的方面,这是在表中记录的每一行上重复模型的字符串名称。例如:

型号表:

Schema::create('models', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

注意: 可能无法使用 Model 的名称创建模块,因此您可能需要使用不同的名称来创建它,例如:参考

models 表中的示例数据:

-------------------
| id |    name    |
-------------------
| 10 | App\Scope  |
-------------------
| 11 | App\Skill  |
-------------------

创建models表后,attribute表的结构变为:

属性表:

Schema::create('attributes', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade');
    $table->foreign('model_id')
          ->references('id')
          ->on('models')
          ->onDelete('cascade');
    $table->unsignedInteger('content_id');
    $table->timestamps();
});

现在,我如何在模型内创建正确的关系,以获取候选人或公司用户类型的技能或范围?

我在用户模型中有自定义关系:

public function candidate()
{
    return $this->hasOne(Candidate::class);
}

public function company()
{
    return $this->hasOne(Company::class);
}

现在,我需要在 CandidateCompany 模型中这样的关系:

public function skills()
{
    // Some code here
}

public function scopes()
{
    // Some code here
}

通常像这样获得用户技能或范围:

$user->candidate->scopes
$user->company->skills

如果您对解决我的问题有其他建议,请提出您的建议。如果我在某处犯了错误,请在可能的情况下纠正我。

【问题讨论】:

  • 您是否尝试过在候选人与范围以及公司与技能之间建立一对多的关系?候选人->hasMany(范围::类,'外键','主键');类似的公司和技能?

标签: database laravel database-design eloquent relationship


【解决方案1】:

我认为您的主要 ORM 构造错误在这一行:

$table->boolean('type')->default(0); // 0 = candidate and 1 = company

使用 Laravel 的 ORM 无法解决此问题。您必须将这一行替换为

$table->unsignedInteger('candidate_id')->nullable()->index();
$table->unsignedInteger('company_id')->nullable()->index();

并从那里开始。由于它可以是候选人或公司,因此其中一个值为空。易于检查。由于只有 2 个可能的选项,因此并不真正需要多态关系。一旦你克服了这个检查,你的 ORM 层次结构就会自己勾勒出来。

您只需要注意如果候选人成为公司或反之亦然,确保其他价值无效。这一切都可以在 Model 的 mutators 或个性化的公共函数中完成,因此您不必在 Controllers/Views 中担心它。

例如$user->choice->scopes;,您可以在其中添加用户模型函数getChoiceAttribute()

public function getChoiceAttribute() {
  if ($this->candidate) {
    return $this->candidate;
  }
  if ($this->company) {
    return $this->company;
  }
  return null;
}

如果候选人成为公司,这同样适用于 setter 函数setChoiceAttribute()。这仅适用于您保存或更新记录。

要在视图中了解您是否正在与候选人或公司合作,请查看$user->choice->getTable();

【讨论】:

    猜你喜欢
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多