CakePHP3:从实体调用表函数是个好主意还是坏主意?

CakePHP3:从实体调用表函数是个好主意还是坏主意?,cakephp,model,entity,cakephp-3.0,Cakephp,Model,Entity,Cakephp 3.0,当我有一些实体,我想保存,验证或删除。为什么我必须调用Table方法?例如: $articlesTable = TableRegistry::get('Articles'); $article = $articlesTable->get(12); $article->title = 'CakePHP is THE best PHP framework!'; $articlesTable->save($article); 为什么不是这样: $article->save(

当我有一些实体,我想保存,验证或删除。为什么我必须调用Table方法?例如:

$articlesTable = TableRegistry::get('Articles');
$article = $articlesTable->get(12);

$article->title = 'CakePHP is THE best PHP framework!';
$articlesTable->save($article);
为什么不是这样:

$article->save();
$article->delete()

实现起来非常简单:

在我的文章中,我可以这样做:

namespace App\Model\Entity;
use Cake\ORM\Entity;

class Article extends Entity
{

    public function save()
    {
        $table = TableRegistry::get($this->source());
        $table->save($this);
    }

}
这很有效,但我想知道这是一个坏习惯还是一个好主意


提前感谢:)

TL;DR:从技术上讲,紧耦合的价格很高(这被认为是不好的做法)

<>强>解释:< /强>我不会考虑这个最佳实践,因为实体应该是一个哑数据对象。它不应该包含任何业务逻辑。通常情况下,它不仅仅是一个简单的save调用,还需要实现一些后续逻辑:处理save的成功和失败,并通过更新UI或发送响应来采取相应的行动。此外,还可以有效地将实体与特定表耦合。将哑数据对象转换为实现业务逻辑的对象

从技术上讲,你可以这样做,我认为有框架或ORMs可以这样做,但我不喜欢耦合。我更喜欢尽可能地编写代码

另外,我不认为你会用你的方法保存任何代码行,你只是把它移到一个不同的地方。我看不到任何好处可以证明引入将实体与业务逻辑耦合的合理性


如果您按照自己的方式去做,我会将该方法实现为trait,或者使用一个基本实体类来继承,以避免重复代码。

我想了解更多关于这种方法的信息。我以前没有考虑过CakePHP中的Table vs.Entity类,我也没有从官方文档中领会到这个意图。有没有关于这个话题的更深入的讨论,你可以推荐阅读?我一直在思考集合与个体的区别。因此,处理实体集合的方法放在表类上,而只处理单个实体的方法放在实体类上。但我看到,除了一些琐碎的代码组织之外,这并不能真正完成很多工作。对实体设置器的调用不会委托给表对象,也不会委托给getter。实体是纯哑数据对象。它们表示RDBMS中的一行或基于文档的存储中的文档。问题不仅在于代码组织,还在于分离。其目标是模块化,通过这种简单的维护和可重用性。你可以用10块砖做一些新的东西,如果你用胶水或钉子把它们粘在一起,你就做不到,它们是耦合的,粘在一起的,以后很难分开。软件也是如此。建议阅读:我理解抽象中的关注点分离原则,我可以看到它如何应用于许多其他情况,但我很难将其应用于实体和表。我想我现在明白了。实体是v2使用的更为“愚蠢”的数组的替代品,因此它们所起的作用非常有限。一个实体不需要来自一个表,也不需要将它持久化到一个表。它可能永远不会有
id
,永远不会接收表类在
beforeSave()
期间应用的默认值,等等。正如您所说的,这表明在实体中应该放置哪些方法存在重大限制。例如,不应在实体上放置关系查找,因为实体很容易处于使此类查找毫无意义的状态。但是像
$this->first_name.''这样的常见表示转换$这个->last_name
对一个实体来说是有意义的,因为它不期望任何它自己无法实现的事情。你可以在那里自由地做任何你想做的事情,但是在那里添加业务逻辑从长远来看很可能会让你头疼。如果您立即需要对实体所表示的数据进行处理,那么getter和setter是一个很好的选择。例如,我喜欢添加一个虚拟属性“url”,并在该属性的getter中使用Router::url()将url返回到相关页面。这样,我就不需要在需要URL的任何地方重新声明路由数组。如果要修改实体集合,请参见