咨询:仅通过为表单赋值即可将数据写入Session的实现相关问题
咨询:仅通过为表单赋值即可将数据写入Session的实现相关问题
嘿,看你贴的这段代码,应该是想实现「给表单赋值后自动把数据同步到Session」的效果对吧?先把你没写完的代码补全,方便咱们一起分析:
public function fooAction() { $session = new Session('Boo'); $form = new FooForm(); if($this->getRequest()->isPost()) { $form->setData($this->getRequest()->getPost()); if($form->isValid()) { // do something } else { // display error message } } else { $data = $session->read(); $data['foo'] = $data['foo'] ?? $this->standardFoo; $form->setData($data); } }
目前你这段代码是GET请求时从Session读数据填充表单,但还没实现反向的自动写入。我给你几个实用的实现思路,都是项目里常用的:
最直观的手动写入方案
其实不用追求完全「自动」,在表单验证通过后直接把数据写入Session就好,代码改动最小,也最容易维护:if($form->isValid()) { // 先处理你原本的业务逻辑 // 然后把表单数据同步到Session $session->write($form->getData()); }这种方式能让你明确控制写入时机,避免误操作,新手也能一眼看懂逻辑。
封装Session感知的自定义表单类
如果你真的想做到「赋值即写入」,可以封装一个继承自FooForm的自定义表单类,重写setData方法来实现自动同步:class SessionAwareFooForm extends FooForm { private $session; public function __construct(Session $session) { parent::__construct(); $this->session = $session; } public function setData(array $data) { parent::setData($data); // 一定要加验证判断,别把无效数据存进Session if($this->isValid()) { $this->session->write($data); } return $this; } }然后在控制器里替换成这个自定义表单:
public function fooAction() { $session = new Session('Boo'); // 用带Session自动同步的表单类 $form = new SessionAwareFooForm($session); if($this->getRequest()->isPost()) { $form->setData($this->getRequest()->getPost()); if($form->isValid()) { // do something,这时候数据已经自动写入Session了 } else { // display error message } } else { $data = $session->read(); $data['foo'] = $data['foo'] ?? $this->standardFoo; $form->setData($data); } }这里要注意:GET请求填充表单时也会调用
setData,所以必须加isValid判断,不然会做冗余的写入操作。无侵入的事件监听方案
要是你不想修改表单类,还可以用框架的事件机制(看代码风格你大概率用的是带事件系统的PHP框架),在表单验证通过的事件触发后执行写入:// 在控制器初始化表单后绑定事件 $form->getEventManager()->attach('isValid', function($e) use ($session) { $form = $e->getTarget(); // 只有验证通过时才执行写入 if($e->getReturnValue()) { $session->write($form->getData()); } });这种方式完全不改动原有表单代码,只需要在控制器里配置监听逻辑,灵活性拉满。
最后再提两个避坑点:
- 绝对不要无条件在
setData里写Session,不然用户输入的无效数据也会被存进Session,搞乱你的Session数据。 - 确认你的
Session类的write方法能正确处理数组数据,要是需要序列化的话,记得在方法内部做好处理。
备注:内容来源于stack exchange,提问作者Lucas VB
相关产品推荐
相关产品推荐

