php - Symfony2 表单组件 - 违反 MVC 和 SRP?

标签 php model-view-controller design-patterns symfony single-responsibility-principle

我越多地使用 Symfony2 并与它的形式作斗争,我就越得出结论,它们是一个巨大的可怕的野兽,甚至不应该真正存在。

我看到了这篇文章 here我发现我同意作者的观点。即使这篇文章是针对 Symfony 1.x 的,我认为它仍然适用于 Symfony2 中的 Form 组件。看起来表单组件确实试图在一个地方解决属于模板、 Controller 和模型的问题。这不会严重违反 MVC 和/或 SRP(单一职责原则)吗?

这可能是一个不同的问题,但我觉得它有点相关 - 我还注意到 symfony 的许多可用包都试图解决 View 之外的 View 问题,例如:

KnpMenuBundle - 您在服务器端使用 oo 接口(interface)生成菜单(为什么不在它们所属的 View 层中?)

IvoryCKEditorBundle - 将 textarea 转换为 ckeditor 是在 View 文件中的一行 jquery 中完成的,那么为什么存在这个包?我什至不想数那里的行数。

所以在 Symfony 的核心中似乎到处都存在这些违规行为,还是我只是不明白?

最佳答案

关于表单处理的问题是它违反了 MVC 的定义。这是一个被称为“横切”的问题,过去已经被科学研究过。论文Domain Driven Web Development With WebJinn ,例如,是关于该主题的有趣读物。

例如,考虑表单与 MVC 不同层的关系:

型号:

  • 表单复制域模型 (DM) 的信息结构。如果您更改此结构(例如,通过向数据结构添加字段或向过程添加参数),您还必须调整表格以输入该信息。
  • 他们需要来自您的 DM 的类型信息,以将输入转换为那里所需的类型。
  • 他们需要知道您的 DM 中指定的约束以验证输入。
  • 理想情况下,他们直接从您的 DM 读取数据和向您的 DM 写入数据(例如,通过读取/写入数据结构的字段或通过使用提交的值作为参数调用 DM 中的过程)。

Controller :

  • 表单接收提交的数据并将其发送到 DM。
  • 他们根据验证是否成功来改变程序流程。

查看:

  • 表单呈现为 HTML 标记和属性的复杂结构,它取决于以上所有内容(是否需要一个字段?是否应该显示错误?如何对字段进行排序?在下拉列表中提供哪些选择?等.)

因此,不可能编写一个不涉及所有这些层的表单抽象机制。相反,解决方案是根据 MVC 将表单库本身构建为不同的层和子组件,以实现 SRP。如果您查看 Symfony2 Form 组件,它会做得很好。 ;)

那么为什么它会是这样一头“巨大的可怕野兽”呢?第一个问题是抽象。以一个简单的下拉列表为例。如果我们想重用下拉菜单的代码,我们需要以某种方式对其进行抽象。现在检查上面的列表,即使是这个简单的输入也会触及 MVC 应用程序的所有三个层。您如何将原本应该构造成三个不同部分的东西抽象出来?

第二个问题是特征多样性。表单库永远无法解决开发人员在日常生活中面临的所有问题。因此,所有这些层和抽象机制都需要可扩展,以便您可以使它们的行为完全符合您的要求。

虽然可扩展,但 Form 组件已经解决了数百个您甚至不必再考虑的小问题。如何输入日期,如何使用不同的 UI(下拉菜单、复选框、单选按钮等)选择一个或多个选项列表,如何再次保护表单安全漏洞等等,这些都是我可以写论文的主题关于。

您会发现表单库非常复杂。我们在编写此类“巨大的可怕野兽”时最好的选择是使它们的 API 对于初学者尽可能简单,对于更高级的用户尽可能灵活,并编写大量文档以充分利用其全部功能。最后一点肯定仍然缺乏 ( please help! ),但我们正在不断努力解决上述所有问题。

另一方面,不幸的是,将复杂问题简化为简单问题是不可能的。

其他更简单的表单库呢?以我的拙见,这些甚至没有尝试解决 Symfony2 Form 组件已经为您解决的大部分问题。 :)

2014 年 1 月 24 日更新: 对于任何想了解更多(更多)的人,这里是 a paper that I published on the subject .

关于php - Symfony2 表单组件 - 违反 MVC 和 SRP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15761785/

相关文章:

php - 使用 PHP-FPM 和 Apache 时如何立即发送 HTTP/2 header

php - Google 验证码未在 GoDaddy 安全 (https) 中显示

asp.net-mvc - 理解和使用 "Service Layers"- .NET MVC 5

c# - 设计一个灵活高效的问答系统

php - 连接 postgres 和 laravel

javascript - 从 jQuery ajax 获取数据

html - 在局部 View 中将两列并排放置

javascript - 使用 jquery val() 方法调用输入值在我的 MVC View 中的空格后不起作用?

wpf - 如何在 M-V-VM 设计模式中最好地表示集合中的可选项目?

design-patterns - Doctrine2 存储库是保存我的实体的好地方吗?