首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何创建优化的模型、表以及它们之间的关系?

如何创建优化的模型、表以及它们之间的关系?
EN

Stack Overflow用户
提问于 2018-10-21 13:31:55
回答 1查看 77关注 0票数 0

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

  • candidates

  • companies

  • scopes

  • skills

  • users

用户表:

代码语言:javascript
复制
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();
});

候选表:

代码语言:javascript
复制
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();
});

公司表:

代码语言:javascript
复制
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();
});

作用域表格:

代码语言:javascript
复制
Schema::create('scopes', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

技能表:

代码语言:javascript
复制
Schema::create('skills', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

在这里,任何用户类型都有作用域和技能。我可以通过创建一个表来解决这个问题:

属性表:

代码语言:javascript
复制
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();
});

attributes表中的示例数据:

代码语言:javascript
复制
----------------------------------------
| id | user_id | model_id | model_type |
----------------------------------------
| 15 |   176   |  34458   | App\Scope  |
----------------------------------------
| 29 |   245   |  17654   | App\Skill  |
----------------------------------------

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

型号表:

代码语言:javascript
复制
Schema::create('models', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->unique();
    $table->timestamps();
});

注意:可能无法使用模型的名称创建模块,因此您可能需要使用其他名称创建它,例如:Reference

models表中的示例数据:

代码语言:javascript
复制
-------------------
| id |    name    |
-------------------
| 10 | App\Scope  |
-------------------
| 11 | App\Skill  |
-------------------

创建models表格后,attribute表格的结构更改为:

属性表:

代码语言:javascript
复制
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();
});

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

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

代码语言:javascript
复制
public function candidate()
{
    return $this->hasOne(Candidate::class);
}

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

现在,我需要内部候选人公司的模型,像这样的关系:

代码语言:javascript
复制
public function skills()
{
    // Some code here
}

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

一般来说,像这样获得用户的技能或范围:

代码语言:javascript
复制
$user->candidate->scopes
$user->company->skills

如果你对解决我的问题还有什么建议,请提出来。如果我在什么地方犯了错,如果可能的话,请纠正我。

EN

回答 1

Stack Overflow用户

发布于 2018-10-22 01:29:29

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

代码语言:javascript
复制
$table->boolean('type')->default(0); // 0 = candidate and 1 = company

这不是使用Laravel的ORM可以解决的。您必须将此行替换为

代码语言:javascript
复制
$table->unsignedInteger('candidate_id')->nullable()->index();
$table->unsignedInteger('company_id')->nullable()->index();

然后从那里开始。因为它既可以是候选人,也可以是公司,其中一个值将为空。很容易检查。由于只有两种可能的选择,因此并不真正需要多态关系。一旦你通过了检查,你的ORM层次结构就会勾勒出它自己的轮廓。

你只需要注意,如果一个候选人成为一家公司,或者反之亦然,你需要确保其他的值被作废。这一切都可以在Model的赋值器或个性化的公共函数中完成,因此您不必在控制器/视图中担心它。

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

代码语言:javascript
复制
public function getChoiceAttribute() {
  if ($this->candidate) {
    return $this->candidate;
  }
  if ($this->company) {
    return $this->company;
  }
  return null;
}

这同样适用于设置器函数setChoiceAttribute(),以防候选人成为一家公司。这仅适用于您保存或更新记录的情况。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52912368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档