章11 -学说整合
在Web项目中,大多数形式用于创建或修改模型对象。这些对象通常序列化在数据库由于一个ORM。ob娱乐下载Symfony的形式系统提供了一个附加层与教义,Symfony的内置ORM,基于这些模型对象的实现形式更容易。
本章会详细说明如何将表单与教条的对象模型。强烈建议您已经熟悉原则及其与symfony的集成。ob娱乐下载如果不是这样,请参考symfob娱乐下载ony和学说的书。
在我们开始之前
在这一章中,我们将创建一篇文章管理系统。让我们先从数据库模式。它是由五个表:文章
,作者
,类别
,标签
,article_tag
,如清单4所示。
清单4 - 1 -数据库模式
/ /配置/理论/模式。yml文章:找:[Sluggable Timestampable]列:标题:类型:字符串(255)notnull:真正的内容:类型:clob状态:字符串(255)author_id:整数category_id添加:整数published_at:时间戳关系:作者:foreignAlias:文章类别:foreignAlias:文章标签:类:标记refClass: ArticleTag foreignAlias:文章作者:列:first_name:字符串(20)last_name:字符串(20)电子邮件:字符串(255)活跃:布尔类别:列:名称:字符串(255)标签:列:名称:字符串(255)ArticleTag:列:article_id:类型:整型主:真正的tag_id:类型:整型主:真正的关系:文章:onDelete:级联标签:onDelete:级联
这里有之间的关系表:
- 其它的关系
文章
表和作者
表:一篇文章是由一个且只有一个作者写的 - 其它的关系
文章
表和类别
表:一篇文章属于一个类别或零 - n n之间的关系
文章
和标签
表
生成表单类
我们想要编辑的信息文章
,作者
,类别
,标签
表。要做到这一点,我们需要创建形式与这些表和配置小部件和验证器相关的数据库模式。即使可以手动创建这些形式,它是一个长而乏味的任务,和整体,它迫使重复同样的信息在几个文件中(列字段名,列和字段的最大长度,…)。此外,每次我们更改模型,我们也必须改变相关的形式类。幸运的是,教义插件有一个内置的任务原则:建立表格的
自动化这个过程生成相关表单对象模型:
美元。/ob娱乐下载 symfony学说:构建表单
表单生成期间,每个表验证器任务创建一个类的每一列使用内省和小部件模型和考虑到关系表。
请注意
的原则:构建所有
和原则:build-all-load
也更新表单类,自动调用原则:建立表格的
的任务。
执行这些任务后,就会创建一个文件结构lib /形式/
目录中。这里是我们的示例模式的创建的文件:
lib /形式/理论/ ArticleForm.class。php ArticleTagForm.class。php AuthorForm.class。php CategoryForm.class。php TagForm.class。php / BaseArticleForm.class基地。php BaseArticleTagForm.class。php BaseAuthorForm.class。php BaseCategoryForm.class。php BaseFormDoctrine.class。php BaseTagForm.class.php
的原则:建立表格的
任务生成两个类为每个表的模式,一个基类lib /形式/基地
目录和一个lib /形式/
目录中。例如,作者
表,包括BaseAuthorForm
和AuthorForm
中生成的类文件lib /形式/基地/ BaseAuthorForm.class.php
和lib / / AuthorForm.class.php形式
。
下表总结了层次结构所涉及的不同的类中AuthorForm
形式的定义。
类 | 包 | 为 | 描述 |
---|---|---|---|
AuthorForm | 项目 | 开发人员 | 覆盖生成的表单 |
BaseAuthorForm | 项目 | ob娱乐下载 | 基于模式和覆盖在每一个执行的原则:建立表格的 任务 |
BaseFormDoctrine | 项目 | 开发人员 | 允许全球定制的教条形式 |
sfFormDoctrine | 教义插件 | ob娱乐下载 | 基础主义形式 |
sfForm | ob娱乐下载 | ob娱乐下载 | symfony的ob娱乐下载基础形式 |
为了创建或编辑的对象作者
类,我们将使用AuthorForm
类,清单4 - 2中描述。你可以注意到,这类不包含任何方法继承的BaseAuthorForm
这是通过配置生成。的AuthorForm
类是我们将使用定制的类并覆盖表单配置。
清单4 - 2 -AuthorForm
类
类AuthorForm扩展BaseAuthorForm{公共函数配置(){}}
清单4 - 3显示了BaseAuthorForm
类的验证器和小部件生成的模型进行内省作者
表。
清单4 - 3 -BaseAuthorForm
类代表的形式作者
表
类BaseAuthorForm扩展BaseFormDoctrine{公共函数设置(){这个美元- >setWidgets(数组(“id”= >新sfWidgetFormInputHidden(),“first_name”= >新sfWidgetFormInputText(),“last_name”= >新sfWidgetFormInputText(),“电子邮件”= >新sfWidgetFormInputText(),));这个美元- >setValidators(数组(“id”= >新sfValidatorDoctrineChoice(数组(“模型”= >“作者”,“列”= >“id”,“要求”= >假)),“first_name”= >新sfValidatorString(数组(“max_length”= >20.,“要求”= >假)),“last_name”= >新sfValidatorString(数组(“max_length”= >20.,“要求”= >假)),“电子邮件”= >新sfValidatorString(数组(“max_length”= >255年)),));这个美元- >widgetSchema- >setNameFormat(“作者(% s)”);这个美元- >errorSchema=新sfValidatorErrorSchema(这个美元- >validatorSchema);父::设置();}公共函数getModelName(){返回“作者”;}}
生成的类看起来非常类似于我们已经在前面章节中创建形式,除了几件事:
- 基类是
BaseFormDoctrine
而不是sfForm
- 发生在验证器和小部件配置
设置()
方法,而不是配置()
方法 - 的
getModelName ()
方法返回相关学说类这种形式
侧边栏
全球主义形式的定制
除了为每个表,生成的类原则:建立表格的
还会生成一个BaseFormDoctrine
类。这个空类其他生成的类的基类/ lib /形式/基地
目录,允许配置全球主义形式的行为。例如,它可以很容易地更改默认格式化程序为所有教义形式:
文摘类BaseFormDoctrine扩展sfFormDoctrine{公共函数设置(){sfWidgetFormSchema::setDefaultFormFormatterName(“div”);}}
你会注意到BaseFormDoctrine
类继承自sfFormDoctrine
类。这个类包含了特定功能主义和其他交易对象序列化在数据库的值提交表单。
提示基类使用设置()
方法配置的配置()
方法。这允许开发人员覆盖空的配置生成的类没有处理父::配置()
调用。
表单字段的名称是相同的,我们组的列名称的模式:id
,first_name
,last_name
,电子邮件
。
的每一列作者
表,原则:建立表格的
任务生成小部件和一个验证器根据模式定义。任务总是生成最安全的验证器。让我们考虑一下id
字段。我们可以检查,如果值是一个有效的整数。相反,这里的验证器生成允许我们也验证标识符(编辑现有对象)或实际存在的标识符是空的(这样我们就可以创建一个新的对象)。这是一个强大的验证。
生成的表单可以立即使用。添加一个< ? php回声美元的形式? >
声明,这将允许创建和验证功能的形式而无需编写一行代码。
除了快速制作原型的能力,生成的形式很容易扩展,而不必修改生成的类。这是由于遗传机制的基础,形成类。
最后在每个数据库模式的演变,任务允许再次生成表单考虑模式修改,没有覆盖定制也许你做了。
CRUD生成器
现在有生成的表单类,让我们来看看是多么容易创建一个symfony模块从浏览器处理的对象。ob娱乐下载我们希望创建、修改和删除对象文章
,作者
,类别
,标签
类。让我们先从模块创建的作者
类。即使我们可以手动创建一个模块,教义插件提供了原则:generate-module
任务生成一个CRUD模块根据教义对象模型类。我们在前一节中生成的使用形式:
美元。/ob娱乐下载 symfony学说:generate-module前端作者作者
的原则:generate-module
有三个参数:
前端
:你想要创建的应用程序模块的名称作者
:您想创建的模块的名称作者
:模型类的名称你想创建的模块
请注意
CRUD代表创建/检索/更新/删除和总结了四个基本操作我们可以执行与模型数据。
在清单4中,我们可以看到,六个动作让我们生成的任务列表(指数
),保存新(创建
),显示新(新
)、修改(编辑
),保存(更新
)和删除(删除
)的对象作者
类。
清单4 - 4 -authorActions
类生成的任务
/ /应用程序/前端/模块/作者/行动/ actions.class.php类authorActions扩展sfActions{公共函数executeIndex(){这个美元- >author_list=学说::可以获得的(“作者”)- >createQuery(“一个”)- >执行();}公共函数executeNew(sfWebRequest美元的请求){这个美元- >形式=新AuthorForm();}公共函数executeCreate(sfWebRequest美元的请求){这个美元- >forward404Unless(美元的请求- >isMethod(“职位”));这个美元- >形式=新AuthorForm();这个美元- >processForm(美元的请求,这个美元- >形式);这个美元- >setTemplate(“新”);}公共函数executeEdit(sfWebRequest美元的请求){这个美元- >forward404Unless(美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”)),sprintf(对象不存在作者(% s)”。,美元的请求- >getParameter(“id”)));这个美元- >形式=新AuthorForm(美元的作者);}公共函数executeUpdate(sfWebRequest美元的请求){这个美元- >forward404Unless(美元的请求- >isMethod(“职位”)| |美元的请求- >isMethod(“把”));这个美元- >forward404Unless(美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”)),sprintf(对象不存在作者(% s)”。,美元的请求- >getParameter(“id”)));这个美元- >形式=新AuthorForm(美元的作者);这个美元- >processForm(美元的请求,这个美元- >形式);这个美元- >setTemplate(“编辑”);}公共函数executeDelete(sfWebRequest美元的请求){美元的请求- >checkCSRFProtection();这个美元- >forward404Unless(美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”)),sprintf(对象不存在作者(% s)”。,美元的请求- >getParameter(“id”)));美元的作者- >删除();这个美元- >重定向(“作者/指数”);}受保护的函数processForm(sfWebRequest美元的请求,sfForm美元的形式){美元的形式- >绑定(美元的请求- >getParameter(美元的形式- >getName()));如果(美元的形式- >isValid()){美元的作者=美元的形式- >保存();这个美元- >重定向(“作者/编辑? id =”。美元的作者- >getId());}}}
在这个模块中,形成生命周期由四个方法:创建
,编辑
,更新
和processForm
。你可以选择来减少这个详细的将这四个任务移动到一个方法,清单4 - 5显示了一个简化的例子。
清单4 - 5 -生命周期的形式authorActions
类后一些重构
/ /在authorActions,取代了创建、编辑、更新和processForm方法公共函数executeEdit(美元的请求){这个美元- >形式=新AuthorForm(原则::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”)));如果(美元的请求- >isMethod(“职位”)){这个美元- >形式- >绑定(美元的请求- >getParameter(“作者”));如果(这个美元- >形式- >isValid()){美元的作者=这个美元- >形式- >保存();这个美元- >重定向(“作者/编辑? id =”。美元的作者- >getId());}}}
请注意
遵循使用默认的例子,更详细的风格你需要相应地做出调整,如果您希望遵循清单4 - 5中的方法。例如,在表单模板,您只需要点的形式编辑动作无论对象是新的或旧的。
任务也生成三个模板和部分,indexSuccess
,editSuccess
,欧宝平台是合法的吗newSuccess
和_form
。的_form
没有使用模板生成< ? php回声美元的形式? >
声明。我们可以修改这个行为,使用——non-verbose-templates
:
美元。/ob娱乐下载 symfony学说:generate-module前端作者作者——non-verbose-templates
这个选项是有用的在原型阶段,如清单4 - 6所示。
清单4 - 6 -_form
模板
/ /应用程序/前端/模块/作者/模板/ _form.php< ? phpinclude_stylesheets_for_form(美元的形式)? >< ? phpinclude_javascripts_for_form(美元的形式)? ><表单动作=“< ?php echo url_for(“作者/”。(美元形式- > getObject () - > isNew () ?“创建”:“更新”)。(! $形式- > getObject () - > isNew () ?“? id =”。美元形式- > getObject () - > getId (): ")) ? > "方法=“职位”< ? php美元的形式- >isMultipart()和打印' enctype =“多部分/格式”> > ?< ? php如果(!美元的形式- >getObject()- >isNew()):? >< input type =“隐藏”name =“sf_method”值=“把”/ >< ? phpendif;? ><表> < tfoot > < tr > < td colspan =“2”> “< ?php echo url_for(“作者/指数”)? > ">取消< / >< ? php如果(!美元的形式- >getObject()- >isNew()):? >< ? php回声link_to(“删除”,“作者/删除? id =”。美元的形式- >getObject()- >getId(),数组(“方法”= >“删除”,“确认”= >“你确定吗?”))? >< ? phpendif;? >< input type =“提交”值=“保存”/ > < / td > < / tr > < / tfoot > < tbody >< ? php回声美元的形式? >< / tbody > < /表> > < /形式
提示
的——用指
选择让我们生成一个动作和一个模板,我们可以使用它来查看对象(只读)。
你现在可以打开URL/ frontend_dev.php /作者
在浏览器中查看生成的模块(图4 - 1和图4 - 2)。花时间玩的接口。感谢您可以列出作者所生成的模块,添加一个新的组,编辑,修改甚至删除。你还会注意到验证规则也工作。注意,在下图中,我们选择删除“活跃”字段。
图4 - 1 -作者列表
图4 - 2——编辑作者验证错误
我们现在可以重复的操作文章
类:
美元。/ob娱乐下载 symfony学说:generate-module前端文章文章——non-verbose-templates
的ArticleForm
形式使用sfWidgetFormDoctrineSelect
小部件来代表之间的关系文章
对象和作者
对象。这个小部件与作者创建了一个下拉列表。在展示期间,作者对象转换成一个字符串的字符使用__toString ()
神奇的方法,必须定义的作者
类,如清单4 - 7所示。
清单4 - 7——实现__toString ()
方法作者
类
类作者扩展BaseAuthor{公共函数__toString(){返回这个美元- >getFirstName()。' '。这个美元- >getLastName();}}
就像作者
类,你可以创建__toString ()
我们的模型的其他类的方法:文章
,类别
,标签
。
请注意
sfDoctrineRecord将尝试猜基准__toString()方法如果你不指定自己的。检查列命名为“名称”,“标题”,“描述”、“主题”、“关键字”,最后“id”使用的字符串表示。如果没有找到这些领域之一,学说将返回一个默认警告字符串。
提示
的方法
选择的sfWidgetFormDoctrineSelect
小部件变化方法用于表示一个对象的文本格式。
图4显示了如何创建一篇文章后实施__toString ()
方法。
图4 - 4 -创建一篇文章
请注意
图4 - 4中你会注意到有些字段没有出现在形式,例如created_at
和updated_at
。这是因为我们定制的类。您将学习如何做这在下一节中。
定制生成的形式
的原则:建立表格的
和原则:generate-module
任务让我们创建功能symfony的模块列表,创建、编辑和删除模ob娱乐下载型对象。这些模块不仅考虑到模型的验证规则,也表之间的关系。所有这一切发生,无需编写一行代码!
时间已经来定制生成的代码。如果表单类已经考虑许多元素,某些方面需要定制。
配置验证器和小部件
让我们先从配置默认情况下生成的验证器和小部件。
的ArticleForm
形式有鼻涕虫
字段。蛞蝓是一串字符,惟一地表示这篇文章的URL。例如,“鼻涕虫”的一篇文章的标题是“用symfony优化发展”ob娱乐下载12-optimize-the-developments-with-ob娱乐下载symfony
,12
在这篇文章id
。这个领域通常保存时自动计算对象,根据标题
,但它有可能是由用户显式地覆盖。即使模式中这个字段是必需的,它不能强制形式。这就是为什么我们修改验证器,使其可选的,如清单4 - 8所示。我们还将定制内容
场扩大其规模,并迫使用户输入至少5个字符。
清单4 - 8 -定制验证器和小部件
类ArticleForm扩展BaseArticleForm{公共函数配置(){这个美元- >validatorSchema(“鼻涕虫”]- >setOption(“要求”,假);这个美元- >validatorSchema(“内容”]- >setOption(“min_length”,5);这个美元- >widgetSchema(“内容”]- >setAttributes(数组(“行”= >10,“关口”= >40));}}
我们在这里使用validatorSchema
和widgetSchema
对象作为PHP数组。这些数组字段的名称作为键和返回分别validator对象和相关部件对象。我们可以单独定制字段和小部件。
请注意
为了允许使用对象作为PHP数组sfValidatorSchema
和sfWidgetFormSchema
类实现ArrayAccess
接口,可在PHP从版本5。
确保两篇文章不能有相同的鼻涕虫
,添加了一个唯一性约束模式定义。这个约束在数据库级是反映在ArticleForm
形式使用sfValidatorDoctrineUnique
验证器。这个验证器可以检查任何形式的独特性。是很有帮助的其他检查的唯一性的一个电子邮件地址登录。清单4 - 9日显示了如何使用它的ArticleForm
的形式。
清单4 - 9日——使用sfValidatorDoctrineUnique
验证器检查领域的独特性
类BaseArticleForm扩展BaseFormDoctrine{公共函数设置(){/ /……这个美元- >validatorSchema- >setPostValidator(新sfValidatorDoctrineUnique(数组(“模型”= >“文章”,“列”= >数组(“鼻涕虫”))));}}
的sfValidatorDoctrineUnique
验证器是一个postValidator
整个数据集上运行后个人每个字段的验证。为了验证的独特性鼻涕虫
,验证器不仅必须能够访问鼻涕虫
值,而且主键(s)的价值。在创建和验证规则确实是不同版自蛞蝓可以保持不变在一篇文章的更新。
现在让我们定制活跃的
场的作者
表,用于显示如果一个作者是活跃的。清单4到10显示了如何排除不活跃的作者ArticleForm
形式,修改查询
选择的FormDoctrineSelect
小部件连接到author_id
字段。的查询
选择接受教义查询对象,允许我们缩小滚动列表中的可用选项的列表。
清单4到10 -定制sfWidgetFormDoctrineSelect
小部件
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……美元的查询= Doctrine_Query::创建()- >从(“作者”)- >在哪里(”一个。积极= ?”,真正的);这个美元- >widgetSchema(“author_id”]- >setOption(“查询”,美元的查询);}}
即使小部件定制可以让我们缩小可用选项的列表,我们不能忘了考虑这个验证器级别的缩小,如清单4所示。就像sfWidgetProperSelect
小部件,sfValidatorDoctrineChoice
验证器接受一个查询
选择缩小选项字段有效。
清单4 -定制sfValidatorDoctrineChoice
验证器
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……美元的查询= Doctrine_Query::创建()- >从(“作者”)- >在哪里(”一个。积极= ?”,真正的);这个美元- >widgetSchema(“author_id”]- >setOption(“查询”,美元的查询);这个美元- >validatorSchema(“author_id”]- >setOption(“查询”,美元的查询);}}
在前面的例子中,我们定义了查询
直接对象配置()
方法。在我们的项目中,这个查询肯定会帮助在其他情况下,最好是创建一个getActiveAuthorsQuery ()
方法在AuthorTable
类和调用这个方法ArticleForm
如清单4 - 12所示。
清单4 - 12 -重构查询
在模型中
类AuthorTable扩展Doctrine_Table{公共函数getActiveAuthorsQuery(){美元的查询= Doctrine_Query::创建()- >从(“作者”)- >在哪里(”一个。积极= ?”,真正的);返回美元的查询;}}类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……authorQuery美元=学说::可以获得的(“作者”)- >getActiveAuthorsQuery();这个美元- >widgetSchema(“author_id”]- >setOption(“查询”,authorQuery美元);这个美元- >validatorSchema(“author_id”]- >setOption(“查询”,authorQuery美元);}}
改变一个验证器
自电子邮件
被定义为一个字符串(255)
模式中,symfony创建了一ob娱乐下载个sfValidatorString ()
验证器抑制最大长度为255个字符。这一领域也应该得到一个有效的电子邮件,学报》第4 - 14清单替换生成的验证器和一个sfValidatorEmail
验证器。
清单42 -改变电子邮件
的字段验证器AuthorForm
类
类AuthorForm扩展BaseAuthorForm{公共函数配置(){这个美元- >validatorSchema(“电子邮件”]=新sfValidatorEmail();}}
添加一个验证器
在前面的章节中,我们观察到如何修改生成的验证器。但在的情况下电子邮件
领域,这将是有用的保持最大长度验证。学报》第4 - 14在清单中,我们使用sfValidatorAnd
验证器,以保证电子邮件有效性和检查字段的最大长度允许。
学报》第4 - 14清单——使用多个验证器
类AuthorForm扩展BaseAuthorForm{公共函数配置(){这个美元- >validatorSchema(“电子邮件”]=新sfValidatorAnd(数组(新sfValidatorString(数组(“max_length”= >255年)),新sfValidatorEmail(),));}}
前面的例子并不是完美的,因为如果我们决定以后修改的长度电子邮件
字段在数据库模式,我们将不得不考虑它还在表单中。而不是取代生成的验证器,最好添加一个,见清单4-15。
清单4-15——添加一个验证器
类AuthorForm扩展BaseAuthorForm{公共函数配置(){这个美元- >validatorSchema(“电子邮件”]=新sfValidatorAnd(数组(这个美元- >validatorSchema(“电子邮件”],新sfValidatorEmail(),));}}
改变一个小部件
在数据库模式状态
场的文章
表存储文章地位一串字符。可能的值被定义的ArticeTable
类,如清单4-16所示。
清单4-16 -定义可用的状态ArticleTable
类
类ArticleTable扩展Doctrine_Table{静态受保护的美元的状态=数组(“草案”,“在线”,“离线”);静态公共函数的getstatus(){返回自我::美元的状态;}/ /……}
编辑一篇文章时,状态
字段必须表示为一个下拉列表,而不是一个文本字段。为此,让我们改变我们使用的小部件,如清单4-17所示。
清单4-17——改变的小部件状态
场
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……这个美元- >widgetSchema(“状态”]=新sfWidgetFormSelect(数组(“选择”= > ArticleTable::的getstatus()));}}
是彻底的我们也必须改变验证器,确保所选的状态实际上属于可能的选项列表(清单4-18)。
清单4-18——修改状态
字段验证器
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……美元的状态= ArticleTable::的getstatus();这个美元- >widgetSchema(“状态”]=新sfWidgetFormSelect(数组(“选择”= >美元的状态));这个美元- >validatorSchema(“状态”]=新sfValidatorChoice(数组(“选择”= >中的(美元的状态)));}}
删除一个字段
的文章
表有三个特别的列,created_at
,updated_at
和published_at
。前两个是自动由教义的一部分timestampable
行为,第三我们日后将处理在我们自己的代码。我们必须删除它们从表单清单4-19显示,防止用户修改它们。
清单4-19 -删除字段
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……设置(这个美元- >validatorSchema(“created_at”]);设置(这个美元- >widgetSchema(“created_at”]);设置(这个美元- >validatorSchema(“updated_at”]);设置(这个美元- >widgetSchema(“updated_at”]);设置(这个美元- >validatorSchema(“published_at”]);设置(这个美元- >widgetSchema(“published_at”]);}}
为了删除一个字段,需要删除它的验证器和小部件。清单4显示了如何还可以删除在一个动作,使用形式作为一个PHP数组。
清单4 -删除字段使用的形式作为一个PHP数组
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……设置(这个美元(“created_at”],这个美元(“updated_at”],这个美元(“published_at”]);}}
总结
总之,清单4-21和清单4-22显示ArticleForm
和AuthorForm
正如我们所定制的表单。
清单4-21 -ArticleForm
形式
类ArticleForm扩展BaseArticleForm{公共函数配置(){authorQuery美元=学说::可以获得的(“作者”)- >getActiveAuthorsQuery();/ /部件这个美元- >widgetSchema(“内容”]- >setAttributes(数组(“行”= >10,“关口”= >40));这个美元- >widgetSchema(“状态”]=新sfWidgetFormSelect(数组(“选择”= > ArticleTable::的getstatus()));这个美元- >widgetSchema(“author_id”]- >setOption(“查询”,authorQuery美元);/ /验证器这个美元- >validatorSchema(“鼻涕虫”]- >setOption(“要求”,假);这个美元- >validatorSchema(“内容”]- >setOption(“min_length”,5);这个美元- >validatorSchema(“状态”]=新sfValidatorChoice(数组(“选择”= >中的(ArticleTable::的getstatus())));这个美元- >validatorSchema(“author_id”]- >setOption(“查询”,authorQuery美元);设置(这个美元(“created_at”],这个美元(“updated_at”],这个美元(“published_at”]);}}
清单4-22 -AuthorForm
形式
类AuthorForm扩展BaseAuthorForm{公共函数配置(){这个美元- >validatorSchema(“电子邮件”]=新sfValidatorAnd(数组(这个美元- >validatorSchema(“电子邮件”],新sfValidatorEmail(),));}}
使用原则:建立表格的
任务让我们自动生成的大部分元素允许形式反思对象模型。自动化是有用的几个原因:
这让开发人员的生活更加轻松,拯救他脱离重复和冗余的工作。他可以集中在验证器和小部件定制根据项目的具体的业务规则。
更新数据库模式时,生成的形式将自动更新。开发人员将只需要调整他们的定制。
下一节将描述行为和定制的模板生成的原则:generate-module
的任务。
形式序列化
前一节中向我们展示了如何自定义形式生成的任务原则:建立表格的
。在当前的部分,我们将自定义生命周期的形式,从生成的代码开始原则:generate-module
的任务。
默认值
一种学说总是连接到一个教义对象实例。关联原则返回的对象总是属于类getModelName ()
方法。例如,AuthorForm
形式只能属于与对象作者
类。这个对象是一个空的对象(一个空白的实例作者
类),或者对象发送给构造函数的第一个参数。而“标准”形式的构造函数将一个数组的值作为第一个参数,一个教条形式主义对象的构造函数。该对象用于定义每个表单字段的默认值。的getObject ()
方法返回当前实例和相关的对象isNew ()
方法指示对象是否是否通过构造函数:
/ /创建一个新的对象authorForm美元=新AuthorForm();打印authorForm美元- >getObject()- >getId();/ /输出零打印authorForm美元- >isNew();/ /输出真正的/ /修改一个现有的对象美元的作者=学说::可以获得的(“作者”)- >找到(1);authorForm美元=新AuthorForm(美元的作者);打印authorForm美元- >getObject()- >getId();/ /输出1打印authorForm美元- >isNew();/ /输出错误
处理生命周期
当我们观察到这一章的开始,新
,编辑
和创建
行动,清单4-23所示,处理生命周期。
清单4-23 -executeNew
,executeEdit
,executeCreate
和processForm
的方法作者
模块
/ /应用程序/前端/模块/作者/行动/ actions.class.php类authorActions扩展sfActions{/ /……公共函数executeNew(sfWebRequest美元的请求){这个美元- >形式=新AuthorForm();}公共函数executeCreate(sfWebRequest美元的请求){这个美元- >forward404Unless(美元的请求- >isMethod(“职位”));这个美元- >形式=新AuthorForm();这个美元- >processForm(美元的请求,这个美元- >形式);这个美元- >setTemplate(“新”);}公共函数executeEdit(sfWebRequest美元的请求){这个美元- >forward404Unless(美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”)),sprintf(对象不存在作者(% s)”。,美元的请求- >getParameter(“id”)));这个美元- >形式=新AuthorForm(美元的作者);}受保护的函数processForm(sfWebRequest美元的请求,sfForm美元的形式){美元的形式- >绑定(美元的请求- >getParameter(美元的形式- >getName()));如果(美元的形式- >isValid()){美元的作者=美元的形式- >保存();这个美元- >重定向(“作者/编辑? id =”。美元的作者- >getId());}}}
即使编辑
动作看起来像我们可能描述的行为在前面的章节中,我们可以指出一些差异:
对象的一个原则
作者
类是作为第一个参数发送表单构造函数:美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”));这个美元- >形式=新AuthorForm(美元的作者);
小部件的
的名字
属性格式自动检索,以便检索输入数据的PHP数组命名的相关表:美元的形式- >绑定(美元的请求- >getParameter(美元的形式- >getName()));
当表单是有效的,仅调用
save ()
方法创建或更新相关学说对象形式:美元的作者=美元的形式- >保存();
创建和修改一个教义对象
清单4-23代码处理对象的创建和修改作者
类:
创建一个新的
作者
对象:的
创建
行动被称为的
形式
然后与一个空对象作者
教义对象的
形式- > save ()
因此创建一个新电话作者
当一个有效的表单提交对象
修改一个现有的
作者
对象:的
更新
被称为一个行动id
参数($请求- > getParameter (id)
站的主键作者
对象是修改)的调用
find ()
方法返回作者
对象相关的主键的
形式
因此与先前发现的对象的
形式- > save ()
调用更新作者
当一个有效的表单提交对象
的save ()
方法
当一个原则是有效的形式,save ()
方法更新相关的对象,并将其存储在数据库中。这种方法实际上商店不仅主要对象也可能相关的对象。例如,ArticleForm
更新一篇文章标签连接形式。之间的关系文章
表和标签
表是一个n n关系,相关标签保存在一篇文章article_tag
表(使用saveArticleTagList ()
生成的方法)。
为了保证一致的序列化,save ()
方法包括每次更新在一个事务中。
请注意
我们将看到在第9章save ()
国际化表方法也会自动更新。
侧边栏
使用bindAndSave ()
方法
的bindAndSave ()
方法结合用户提交表单的输入数据,验证此表格并更新相关对象在数据库中,所有在一个操作:
类articleActions扩展sfActions{公共函数executeCreate(sfWebRequest美元的请求){这个美元- >形式=新ArticleForm();如果(美元的请求- >isMethod(“职位”)& &这个美元- >形式- >bindAndSave(美元的请求- >getParameter(“文章”))){这个美元- >重定向(“文章/创建”);}}}
处理文件上传
的save ()
方法自动更新原则对象但不能处理元素,如管理文件上传。
让我们看一下如何将文件附加到每一篇文章。文件存储在web /上传
目录和参考的文件路径保存文件
场的文章
表,如清单4-24所示。
清单4-24——模式文章
表和相关文件
/ /配置/理论/模式。yml文章:/ /……文件:字符串(255)
每个模式更新之后,您需要更新对象模型,数据库和相关的形式:
美元。/ob娱乐下载 symfony学说:构建所有
谨慎
请注意,原则:构建所有
任务删除之前每个模式表重新创建它们。表内的数据覆盖。这就是为什么重要的是要创建测试数据(固定装置
),您可以将每个模型加载后再修改。
清单4-25展示了如何修改ArticleForm
类为了链接一个部件和一个验证器文件
字段。
清单4-25——修改文件
场的ArticleForm
的形式。
类ArticleForm扩展BaseArticleForm{公共函数配置(){/ /……这个美元- >widgetSchema(“文件”]=新sfWidgetFormInputFile();这个美元- >validatorSchema(“文件”]=新sfValidatorFile();}}
至于每个表单允许文件上传,不要忘记添加的enctype
属性的形式
标签模板(见第二章为进一步的信息关于文件上传管理)。
提示
在创建表单模板时,您可以检查如果表单包含文件字段,并添加的enctype
属性自动:
< ? php如果(美元的形式- >isMultipart()回声' enctype =“多部分/格式”;? >
这段代码创建的表单时自动添加generate-module任务。
清单4-26显示了修改申请在保存表单上传文件到服务器和存储的路径文章
对象。
清单4-26 -保存文章
对象和文件上传的行动
公共函数executeEdit(美元的请求){美元的作者=学说::可以获得的(“作者”)- >找到(美元的请求- >getParameter(“id”));这个美元- >形式=新ArticleForm(美元的作者);如果(美元的请求- >isMethod(“职位”)){这个美元- >形式- >绑定(美元的请求- >getParameter(“文章”),美元的请求- >getfile(“文章”));如果(这个美元- >形式- >isValid()){美元的文件=这个美元- >形式- >getValue(“文件”);美元的文件名=sha1(美元的文件- >getOriginalName())。美元的文件- >getExtension(美元的文件- >getOriginalExtension());美元的文件- >保存(sfConfig::得到(“sf_upload_dir”)。' / '。美元的文件名);美元的文章=这个美元- >形式- >保存();这个美元- >重定向(“文章/编辑? id =”。美元的文章- >getId());}}}
保存在文件系统允许上传文件sfValidatedFile
对象知道文件的绝对路径。在调用save ()
方法,用于更新相关对象的字段值,至于文件
场,sfValidatedFile
对象是字符串的转换__toString ()
方法,发送文件的绝对路径。的文件
列的文章
表将存储这绝对路径。
提示
如果您希望存储路径相对于sfConfig: get (“sf_upload_dir”)
从目录中,您可以创建一个类继承sfValidatedFile
并使用validated_file_class
选择发送的sfValidatorFile
验证器新类的名称。验证器将返回您的类的一个实例。我们将在本章的其余部分的另一个方法,在修改的值组成文件
列之前保存在数据库对象。
自定义save ()
方法
我们观察到在前一节中如何保存上传文件编辑
行动。面向对象编程的原则之一是代码的可重用性,由于其封装在类。而不是复制用于保存文件的代码在每个操作使用ArticleForm
形式,最好是在移动ArticleForm
类。清单速率显示了如何覆盖save ()
方法以保存文件和可能删除现有的文件。
清单速率——覆盖save ()
的方法ArticleForm
类
类ArticleForm扩展BaseFormDoctrine{/ /……公共函数保存(反对美元=零){如果(file_exists(这个美元- >getObject()- >getFile())){拆开(这个美元- >getObject()- >getFile());}美元的文件=这个美元- >getValue(“文件”);美元的文件名=sha1(美元的文件- >getOriginalName())。美元的文件- >getExtension(美元的文件- >getOriginalExtension());美元的文件- >保存(sfConfig::得到(“sf_upload_dir”)。' / '。美元的文件名);返回父::保存(反对美元);}}
移动代码的形式后,编辑
行动最初生成的代码是一样的原则:generate-module
的任务。
侧边栏
重构代码的模型形式
生成的行为原则:generate-module
任务通常不应该被修改。
你可以添加的逻辑编辑
行动,特别是在序列化形式,通常应该搬到模型的类或类的形式。
我们只是走过去形式类的重构的一个例子为了考虑存储一个上传文件。让我们看看另一个例子与模型有关。的ArticleForm
形式有鼻涕虫
字段。我们发现这个领域应该是自动计算的标题
领域,它可能会被用户。这个逻辑不依赖于形式。因此属于模型,如以下代码所示:
类文章扩展BaseArticle{公共函数保存(反对美元=零){如果(!这个美元- >getSlug()){这个美元- >setSlugFromTitle();}返回父::保存(反对美元);}受保护的函数setSlugFromTitle(){/ /……}}
这个重构的主要目的是尊重的分离应用程序层,并促进reusibility。
自定义doSave ()
方法
我们观察到对象的保存是在一个事务,以保证每个操作相关的储蓄是正确处理。当覆盖save ()
方法是在前一节中为了保存上传文件,执行代码独立于该事务。
清单4-28显示了如何使用doSave ()
方法在全球事务中插入我们的代码保存上传文件。
清单4-28——覆盖doSave ()
方法ArticleForm
形式
类ArticleForm扩展BaseFormDoctrine{/ /……受保护的函数doSave(反对美元=零){如果(file_exists(这个美元- >getObject()- >getFile())){拆开(这个美元- >getObject()- >getFile());}美元的文件=这个美元- >getValue(“文件”);美元的文件名=sha1(美元的文件- >getOriginalName())。美元的文件- >getExtension(美元的文件- >getOriginalExtension());美元的文件- >保存(sfConfig::得到(“sf_upload_dir”)。' / '。美元的文件名);返回父::doSave(反对美元);}}
的doSave ()
方法被调用的事务创建的save ()
方法,如果调用save ()
的方法文件()
抛出一个异常对象,该对象将不会被保存。
自定义updateObject ()
方法
有时需要修改对象之间的连接形式更新和保存在数据库中。
在我们的文件上传示例中,而不是存储上传文件的绝对路径文件
列,相对于我们希望存储路径sfConfig: get (“sf_upload_dir”)
目录中。
清单4-29显示了如何覆盖updateObject ()
的方法ArticleForm
为了改变的价值文件
列后自动更新对象但之前保存。
清单4-29——覆盖updateObject ()
方法和ArticleForm
类
类ArticleForm扩展BaseFormDoctrine{/ /……公共函数updateObject(美元的价值=零){美元的对象=父::updateObject(美元的价值);美元的对象- >setFile(str_replace(sfConfig::得到(“sf_upload_dir”)。' / ',”,美元的对象- >getFile()));返回美元的对象;}}
的updateObject ()
方法被调用的doSave ()
方法之前保存在数据库对象。
这项工作在Creative Commons许可Attribution-Share都3.0 Unported许可执照。