vlambda博客
学习文章列表

我的 Symfony 和 Doctrine 的最佳实践经验

虽然 symfony 和 doctrine 的强大功能可以让我们的开发变得快捷,但不合理运用也容易导致恼人的问题出现。我就我的经验以及对程序设计的认识,来说说我总结的最佳实践。


首先从 mvc 的角度来说,symfony 提供了完整的 controller 和 view 层的解决方案,而 doctrine 则是提供了 m 层的解决方案。作为 mvc 里面的最底层,model 是不需要知道 controller 和 view 的存在的。具体体现在运用上,举个例子,当使用 doctrine 的 model 代码直接移植到 zend framework 或者其他框架环境下,应该是无缝移植而不用修改 model 任何代码。如果你的 model 层里面使用了类似 sfConfig::get 这样的 symfony 框架提供的方法,那么你 model 代码里面就出现了“坏味道”,将直接导致你的 model 层不能被复用。


事实上,就算是 symfony 这一个框架,也是包含了两个环境的:web 应用环境和命令行环境。所以如果你不小心在 model 层里面写上了类似 sfContext::getInstance()->getRequest() 这样的代码,那么在使用会运行 model 的命令比如 symfony doctrine:data-load 的时候,就很有可能因为找不到某个组件而发生错误。比如上面的代码,命令行环境的上下文(context)是没有 request 组件的。

为了防止这样的“坏味道”出现,model 层应尽量避免代码里面直接获取某一个变量(比如使用 sfConfig),而多提供丰富的参数或者 setter 接口。从设计的角度来说,跟 controller 或者 view 关系比较紧密的变量(比如列表页最多显示多少条啦等等),也的确不应该让 model 层来关心。

接下来说说载入测试数据的方法。在实际的使用过程中,很多人会发现,如果使用了 DoctrineRecord 的 save 方法做了一些初始化工作,而且这些初始化工作是新增了另外的 DoctrineRecord 对象的时候,如果测试数据同时又对初始化工作提到的对象有描述,往往会发生关联冲突的情况发生。为了避免这种错误,有两种方法可以选择,一是不要用 save 方法来做初始化工作,而是制造新的创建对象的方法,比如用户注册可以用 User::register ;二是不要使用 doctrine:data-load 命令来载入数据。我这里更倾向于使用第二种方法,并推荐使用单元测试来完成数据载入的工作。这么做的好处有两个,一是用测试代码载入数据的同时也是做单元测试,保证每次更新代码以后的代码正确性和完整性,二是不会发生 data-load 命令那种冲突问题。不过坏处也是显而易见的:因为还带有测试的目的,所以数据的载入时间会变长。