因此,在将自己的扩展程序花了整整一天的时间来解决这个问题之后,我想在这里分享我的解决方案。需要注意的是,我的实体没有使用EAV系统,每个实体都有自己的平面表,每个属性都有一列。我的实体具有四个datetime属性-其中两个是通过用户输入(open_date
,close_date
)填充的,其中两个是由源代码(create_date
,close_date
)自动填充的。
实体的模型类
在实体的模型类中,我包括以下内容:
- 一种方法来定义和获取什么属性是datetime类型,并通过在店里的本地时间提供用户输入的数据进行填充。
- 一种仅将这些字段从GMT时间转换为商店本地时间的方法(稍后会对此进行详细介绍)。
- _beforeSave()方法会在保存时自动为我设置GMT中的'edit_date'和'create_date'属性(未通过用户输入填充)。
源代码:
/**
* Model's datetime attributes that are populated with user data supplied
* in the store's local time.
*
* @var array
*/
protected $_dateFields = array(
'open_date',
'close_date',
);
/**
* Return the model's datetime attributes that are populated with user
* data supplied in the store's local time.
*
* @return array
*/
public function getDateFields()
{
return $this->_dateFields;
}
/**
* (non-PHPdoc)
* @see Mage_Core_Model_Abstract::_beforeSave()
*/
protected function _beforeSave()
{
parent::_beforeSave();
$date = Mage::getModel('core/date')->gmtDate();
if (!$this->getId()) {
$this->setData('create_date', $date);
}
$this->setData('edit_date', $date);
return $this;
}
实体的管理控制器的saveAction
在控制器的saveAction方法中,我利用了在模型类中定义的getDateFields()方法来知道在保存到日期数据库之前需要从商店的本地时间(用户输入的时间)更改为GMT时间的哪些属性。请注意,这只是我的save方法的部分片段:
....
$data = $this->getRequest()->getPost()
// Convert user input time from the store's local time to GMT time
$dateFields = $model->getDateFields();
if (is_array($dateFields) && count($dateFields)) {
$data = $this->_filterDateTime($data, $dateFields);
$store_timezone = new DateTimeZone(Mage::getStoreConfig('general/locale/timezone'));
$gmt_timezone = new DateTimeZone('Europe/London');
foreach ($dateFields as $key) if (isset($data[$key])) {
$dateTime = new DateTime($data[$key], $store_timezone);
$dateTime->setTimezone($gmt_timezone);
$data[$key] = $dateTime->format('Y-m-d H:i:s');
}
}
$model->addData($data);
try {
$model->save();
....
用于编辑实体的管理表单块
与Magento的管理网格小部件不同,后者期望在GMT中提供集合中的日期时间值,并打算在显示页面之前将这些值转换为商店的本地时间,Magento的管理表单小部件不遵循此行为。相反,表单小部件将按原样接受datetime值,并在不自动调整时间的情况下显示它。因此,由于值存储在GMT的数据库中,因此在将数据提供给表单之前,我们必须先将用户输入的datetime属性转换为商店的本地时间。这就是我们在实体模型类中排名第二的地方。
这是我的管理表单的块类的_prepareForm()方法的一部分(扩展了Mage_Adminhtml_Block_Widget_Form)。我已经省略了大部分函数,试图只包含与此问题相关的最低要求,并且仍然提供了有效的类方法:
protected function _prepareForm()
{
$form = new Varien_Data_Form();
$model = Mage::registry('YOUR_MODEL_CLASS');
$date_format = Mage::app()->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM);
$time_zone = $this->__('Time Zone: %s', Mage::getStoreConfig('general/locale/timezone'));
$calendar_img = $this->getSkinUrl('images/grid-cal.gif');
$fieldset = $form->addFieldset('base_fieldset', array('legend'=> $this->__('General Information')));
$fieldset->addField('open_date', 'datetime', array(
'name' => 'open_date',
'label' => $this->__('Open Date'),
'title' => $this->__('Open Date'),
'time' => 'true',
'image' => $calendar_img,
'format' => $date_format,
'style' => 'width:160px',
'required' => true,
'note' => $time_zone
));
$fieldset->addField('close_date', 'datetime', array(
'name' => 'close_date',
'label' => $this->__('Close Date'),
'title' => $this->__('Close Date'),
'time' => 'true',
'image' => $calendar_img,
'format' => $date_format,
'style' => 'width:160px',
'required' => true,
'note' => $time_zone
));
if ($model->getId()) {
$form->setValues($model->getAdminFormData());
}
$this->setForm($form);
return parent::_prepareForm();
}
大多数情况都遵循Magento的任何其他表单小部件。但是,这里要注意的重要一件事是,而不是打电话给$form->setValues($model->getData())
我们打电话$form->setValues($model->getAdminFormData())
。如果我们从答案的第一部分中查看我的代码,则此方法需要将用户输入的所有日期时间属性从GMT转换为商店的本地时间。
最终结果:
- 所有值均在GMT时间保存到DB中。
- 用户输入的值从GMT转换为商店的本地时间,然后再进行编辑
- 管理网格一如既往地工作,在页面上呈现网格之前,先获取GMT值并转换为商店的本地时间。
希望这被证明是有一天可以帮助别人的宝贵资源。来进行前端开发的时候了,请记住,日期时间值在数据库中的GMT中!