专家:一个重构的故事(4/5)
在最后一部分中,我们了解了如何将代码从控制器到模型中。原理非常简单,你想要薄的控制器和脂肪模型。
今天,我们将看到如何新形式框架可以帮助我们保持干净的关注点分离。
当用户登录作为管理员,他可以每个产品的最新信息和上传一个新的图片。
这一页是管理的编辑
行动的产品
模块:
公共函数executeEdit(){这个美元- >产品= ProductPeer::retrieveByPk(这个美元- >getRequestParameter(“id”));如果(is_null(这个美元- >产品)){这个美元- >forward404();}这个美元- >形式=新ProductForm(这个美元- >产品);如果(sfRequest::帖子= =这个美元- >getRequest()- >getMethod()){这个美元- >形式- >绑定(这个美元- >getRequestParameter(“产品”),这个美元- >getRequest()- >getfile(“产品”));如果(这个美元- >形式- >isValid()){/ /获取当前的产品美元的产品=这个美元- >形式- >getObject();美元图片=这个美元- >形式- >getValue(“图像”);美元的文件名=美元的产品- >getImage();如果(美元图片){/ /删除旧的形象如果(file_exists(美元的文件= sfConfig::得到(“sf_web_dir”)。' /图片/产品/。currentImage美元)){拆开(美元的文件);}}/ /更新产品美元的产品=这个美元- >形式- >updateObject();如果(美元图片){/ /保存新形象美元的文件名=sha1(美元图片- >getOriginalName())。美元图片- >getExtension(美元图片- >getOriginalExtension());美元图片- >保存(sfConfig::得到(“sf_web_dir”)。' /图片/产品/。美元的文件名);}美元的产品- >setImage(美元的文件名);/ /保存产品美元的产品- >保存();这个美元- >getUser()- >setFlash(“通知”,sprintf(的产品“% s”已经成功更新。,美元的产品- >getTitle()));这个美元- >重定向(“产品/指数”);}}}
代码是不言而喻的:
- 产品从模型中检索(
产品
) - 创建一个表单为给定的产品(
ProductForm
) - 如果表单发布(
帖子
请求方法)- 表单验证
- 产品的更新
大部分的代码管理图片上传过程:
- 如果一个图片上传,删除旧的
- 保存新图像与一个唯一的名称
- 改变图像路径
产品
对象
但是代码管理图像上传过程并不真正属于这个控制器,不是吗?
是非常简单的知道代码是在正确的地方。问问自己:我如何重用ProductForm
在我的应用程序?在这个特定的例子中,你需要复制大量的代码。你知道有一个更好的方法来做到这一点。所以,是时候重构。
如果你读过“ob娱乐下载symfony形式在行动“你书,知道表单框架允许一个清洁分离控制器(表单),模型(验证),和视图(小部件)。
让我们把一些代码从操作控制器形式控制器。我想要动作控制器重构后是这个样子:
公共函数executeEdit(){这个美元- >产品= ProductPeer::retrieveByPk(这个美元- >getRequestParameter(“id”));如果(is_null(这个美元- >产品)){这个美元- >forward404();}这个美元- >形式=新ProductForm(这个美元- >产品);如果(sfRequest::帖子= =这个美元- >getRequest()- >getMethod()){这个美元- >形式- >绑定(这个美元- >getRequestParameter(“产品”),这个美元- >getRequest()- >getfile(“产品”));如果(这个美元- >形式- >isValid()){美元的产品=这个美元- >形式- >保存();这个美元- >getUser()- >setFlash(“通知”,sprintf(的产品“% s”已经成功更新。,美元的产品- >getTitle()));这个美元- >重定向(“产品/指数”);}}}
我们已经删除了必须去某个地方的代码。第一个想法是将它移动到形式save ()
方法。但是有一个更好的地方。我们想覆盖的方法updateObject ()
。的updateObject ()
方法是在symfony更新清理的ob娱乐下载对象的值。调用此方法save ()
在一个数据库事务。
所以,这是新的ProductForm
代码:
类ProductForm扩展BaseProductForm{公共函数配置(){设置(这个美元(“created_at”]);这个美元- >widgetSchema(“图像”]=新sfWidgetFormInputFile();这个美元- >validatorSchema(“图像”]=新sfValidatorFile(数组(“要求”= >假));}公共函数updateObject(){美元图片=这个美元- >getValue(“图像”);美元的文件名=这个美元- >对象- >getImage();如果(美元图片){/ /删除旧的形象如果(file_exists(美元的文件= sfConfig::得到(“sf_web_dir”)。' /图片/产品/。美元的文件名)){拆开(美元的文件);}}/ /更新产品父::updateObject();如果(美元图片){/ /保存新形象美元的文件名=sha1(美元图片- >getOriginalName())。美元图片- >getExtension(美元图片- >getOriginalExtension());美元图片- >保存(sfConfig::得到(“sf_web_dir”)。' /图片/产品/。美元的文件名);}这个美元- >对象- >setImage(美元的文件名);}}
作为一个额外的好处,我们只需要保存产品
物体一旦代替以前的两倍。的代码封装为我们有一个相当标准的要好executeEdit ()
操作代码是自解释的ProductForm
可以重用在其他地方很少的努力。
但是现在的逻辑是形式,我们可以做得更好。我们现在直接访问值
变量,我们可以重构代码是这样的:
公共函数updateObject(){如果(美元图片=这个美元- >getValue(“图像”)){/ /删除旧的形象如果(file_exists(美元的文件= sfConfig::得到(“sf_web_dir”)。' /图片/产品/。这个美元- >对象- >getImage())){拆开(美元的文件);}/ /保存新形象美元的文件名=sha1(美元图片- >getOriginalName())。美元图片- >getExtension(美元图片- >getOriginalExtension());美元图片- >保存(sfConfig::得到(“sf_web_dir”)。' /图片/产品/。美元的文件名);}设置(这个美元- >值(“图像”]);/ /更新产品返回父::updateObject();}
这里的技巧是删除图像
值后清理值我们处理它。这样,默认updateObject ()
symfony的方法ob娱乐下载不会更新图像列。你知道文斯希望他的代码是完美的,所以我甚至让它更好地通过创建一个专用的方法,更新图片:
公共函数updateObject(){这个美元- >updateImageColumn();返回父::updateObject();}受保护的函数updateImageColumn(){如果(美元图片=这个美元- >getValue(“图像”)){/ /删除旧的形象如果(file_exists(美元的文件= sfConfig::得到(“sf_web_dir”)。' /图片/产品/。这个美元- >对象- >getImage())){拆开(美元的文件);}/ /保存新形象美元的文件名=sha1(美元图片- >getOriginalName())。美元图片- >getExtension(美元图片- >getOriginalExtension());美元图片- >保存(sfConfig::得到(“sf_web_dir”)。' /图片/产品/。美元的文件名);}设置(这个美元- >值(“图像”]);}
symfonob娱乐下载y 1.2,你甚至可以删除表单代码(
updateObject
和updateImageColumn
)完全推动形式现在所有这些样板式代码自动为你。
总结我们的工作做在前三个部分:我们已经表达了我们的控制器薄通过移动代码模型(ProductPeer
),给用户(myUser
)和形式(ProductForm
)。
在接下来的部分中,我们将看到一些代码仍然必须离开控制器。我们还将学习一些不错的快捷键可用1.1 symfony。ob娱乐下载
评论
评论都关门了。
以确保评论保持相关,他们关闭了旧的帖子。
两个问题:
1)为什么不使用$ this - >形式- > bindAndSave ($ this - > getRequestParameter(“产品”),$ this - > getRequest () - > getfile(“产品”));
2)(不是特定于第4部分)为什么不使用新的美元请求参数如“公共函数executeEdit(请求)美元”?
经常有多种可能性的怎么做,我想听到你喜欢哪一个,为什么。
经常出现的东西对我们处理文件上传时,就像这个:如果其他字段不通过验证,但是文件上传,它通常是一个坏主意来让用户选择并上传文件一遍又一遍。非常缓慢,浏览器需要用户重新选择文件每次形式似乎出于安全原因。
我们已经处理,通过设计推动对象“活”的国旗,不会设置,直到他们完全通过验证。这样我们有一个地方来存储部分(即有效的东西。,large files the use shouldn't have to re-upload just because they had a weird character in the phone number field).
新形式的系统提供一个标准化的解决这个问题吗?
谢谢!
谢谢!
我有同样的问题,只是添加$ this - >对象- > setImage ($ filename);
之前设置的功能。
丹尼尔
$ this - >对象- > setImage ($ filename);
在更新对象没有?