Laravel 中自定义模型中间表(请使用合适的方法来解决问题)

几天前在 tweet 看到这个:

file

我的第一反应是,「一定有」。这种类型的事情,恰恰我觉许多人都是写利害评论,而不是简单的说说,经常掩盖甚至没有意识到。 Laravel 是「顽固的」,但通常意味着有很多默认设置将你推向一种特定风格。多年以来我发现很少的情况下,你不能轻松的覆盖这些;往往,当你实例化时,它只是添加了另一个函数调用。

通常,当我想到我的代码出现 Mark的问题时, 从文档中搜索和发现更直接的答案,在我看来,这是一个很好的例子。

首先,用正常的工作方式检查一下中间表。在这个例子中我们有一个多对多 UsersSubjects 之间的关系。因此,一个典型的 update 语句看起来像是:

User::find($id)->subjects()->updateExistingPivot($subjectId, ['status' => 'enrolled']);

如果你想要在这个语句下调度一个事件或是有其他任务,你可以写在这条语句下面。如果你希望在你的整个项目中使用,你预先把这条语句写成一个服务类函数,这样就可以在任意一个地方 update

这样运行,没有什么内在「错误」。这样 做 感觉有点程序化,不过,难道不是吗? 让你感觉也许有些你可以做的更好?假如,这段代码是全局要使用,但是我们 没有在服务类中创建它?如果在每个不同的操作中,有很多中间表的字段要被更新?

这样编写程序变得「困难」。不是编写代码,而是设计代码。先考虑如何使用这个类,并作出明智的选择,而不是仅仅放在你学习到的技术。因为它很简单,你可以从其他地方复制/粘贴,没有记住它是如何使用的(经验之谈,不要感到是攻击)。

例如,如果这个中间表包含的信息是有用的,本身独立于 users 和特定的 subjects? 这样的情况下,你可能选择建立自己的实体,完整的控制器,模型,验证规则。这个想法在过去一年越来越强烈了;你可能会喜欢听Full Stack Radio插曲 ,DHH讨论如何建立一个 BaseCamp 时的中心思想。 UserSubject也许是事情本身,你创建,更新和报告 。重要的是意识到中间表类在 Laravel默认选择的,而不是可选的。

第二个选项---可能是最常见的---就是按照我们上面描述的方法来创建一个UserSubjectService类。任何时候你想要更新链接数据库,你都要经过服务类的update()函数。这使您可以完全控制流程的每个步骤,同时使所有内容都完全透明。当然,这是完全可以测试的。其中一些缺点可能是不断声明新类的所有开销,将用户,主题和更新数据的实例传递给它,并可能在需要单独更新函数的任何地方调用相同的事件函数。服务类更常用于管理其他几个类,所以如果我们在用户和主题之间做了很多的工作,或者增加了额外的功能,这将是一个不错的选择。对于像我们以后那样简单的事情,这可能太多了。

我会告诉你的最后一个选项就是覆盖Laravel默认值的一个例子。我们已经知道,每个Eloquent模型都有Observers - 内置在模型中的许多常见动作的侦听器钩子中,比如completedsaving...和update。既然我们想在每次数据透视表更新的时候触发一个事件,我们只需要进入这个模型。

雄辩使用了一种叫做「等待」的特殊模式---一个在Illuminate\Database\Eloquent\Relations\Pivot中找到的枢轴,是一个模型的继承类,它具有处理多对多的功能,很多关系。为了定制这些函数中的任何一个,我们首先扩展Pivot,例如class UserSubject extends Pivot来添加我们的代码,然后调用我们的模型关系函数来调用它:

class Subject extends Model
{
    public function users()
    {
        return $this->belongsToMany('App\User')
            ->using('App\UserSubject');
    }
}

现在每当关系被调用的时候,任何你添加到你自己的类中的东西都就像继承的模型一样会被访问。 在这个特定的情况下,我们将注册一个UserSubjectObserver类,并将代码添加到updating()updated()方法中。

三种方法都可以实现同样的事情 -- 但并没有说这所罗列的就是所有的解决方式了。 本文的重点,除了介绍Pivot类和using()函数之外,还让你意识到用Laravel方法来编程的优势,但是最终设计代码还要靠你自己!

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/@codebyjeff/custom-pi...

译文地址:https://learnku.com/laravel/t/7510/custo...

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!