Vì vậy, sau khi dành gần một ngày để chiến đấu với vấn đề tương tự này trong phần mở rộng của riêng tôi, tôi nghĩ tôi sẽ chia sẻ giải pháp của mình ở đây. Một điều cần lưu ý là các thực thể của tôi không sử dụng hệ thống EAV, mỗi thực thể có bảng phẳng riêng với một cột cho mỗi thuộc tính. Thực thể của tôi có bốn thuộc tính datetime-- hai trong số đó được điền từ đầu vào của người dùng ( open_date
, close_date
) và hai trong số đó được nhập tự động bởi mã nguồn ( create_date
, close_date
).
Lớp mẫu của thực thể
Trong lớp mô hình của thực thể tôi bao gồm:
- Một cách để xác định và tìm nạp các thuộc tính của loại thời gian và được điền thông qua dữ liệu nhập vào của người dùng được cung cấp trong giờ địa phương của cửa hàng.
- Một phương thức chuyển đổi chỉ các trường này từ giờ GMT sang giờ địa phương của cửa hàng (nhiều hơn về điều này sau).
- Phương thức _b BeforeSave () tự động đặt các thuộc tính 'edit_date' và 'create_date' ( không được điền thông qua đầu vào của người dùng) trong GMT cho tôi tự động lưu.
Mã nguồn:
/**
* 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 của Trình điều khiển quản trị của thực thể
Trong phương thức saveAction của bộ điều khiển, tôi đã sử dụng phương thức getDateFields () được xác định trong lớp mô hình để biết thuộc tính nào tôi cần thay đổi từ giờ địa phương của cửa hàng (được người dùng nhập vào) vào giờ GMT trước khi lưu vào cơ sở ngày. Lưu ý rằng đây chỉ là một phần của phương thức lưu của tôi:
....
$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();
....
Khối biểu mẫu quản trị để chỉnh sửa thực thể
Không giống như tiện ích lưới quản trị của Magento, dự kiến các giá trị thời gian từ các bộ sưu tập sẽ được cung cấp trong GMT, với ý định chuyển đổi các giá trị này thành giờ địa phương của cửa hàng trước khi hiển thị trang, tiện ích biểu mẫu quản trị viên của Magento không tuân theo hành vi này. Thay vào đó, tiện ích biểu mẫu sẽ chấp nhận giá trị datetime như hiện tại và hiển thị nó mà không tự động điều chỉnh thời gian. Do đó, vì các giá trị được lưu trữ trong cơ sở dữ liệu theo GMT, trước tiên chúng tôi phải chuyển đổi các thuộc tính datetime của người dùng thành thời gian cục bộ của cửa hàng trước khi cung cấp dữ liệu đó cho biểu mẫu. Đây là nơi số 2 của chúng tôi trên Lớp Người mẫu của Thực thể phát huy tác dụng.
Đây là một phần của phương thức _prepareForm () của lớp khối của quản trị viên của tôi (mở rộng Mage_Adminhtml_Block_Widget_Form). Tôi đã bỏ qua phần lớn chức năng của mình, cố gắng chỉ bao gồm mức tối thiểu trần có liên quan đến câu hỏi này và vẫn cung cấp một phương thức lớp hợp lệ:
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();
}
Hầu hết điều này tuân theo bất kỳ tiện ích biểu mẫu nào khác cho Magento. Tuy nhiên, một điều quan trọng cần lưu ý ở đây là thay vì gọi $form->setValues($model->getData())
chúng tôi gọi $form->setValues($model->getAdminFormData())
. Mà, nếu chúng tôi xem xét mã của tôi từ phân đoạn đầu tiên của câu trả lời này, phương thức này sẽ chuyển đổi tất cả các thuộc tính datetime, được người dùng nhập vào, từ GMT sang giờ địa phương của cửa hàng.
Kết quả cuối cùng:
- Tất cả các giá trị được lưu vào DB trong thời gian GMT.
- Các giá trị được nhập của người dùng được chuyển đổi từ GMT sang giờ địa phương của cửa hàng, trước khi đưa nó vào biểu mẫu chỉnh sửa
- Lưới quản trị hoạt động như mọi khi, lấy các giá trị GMT và chuyển đổi sang giờ địa phương của cửa hàng trước khi hiển thị lưới trên trang.
Hy vọng điều này chứng tỏ là một nguồn tài nguyên quý giá để giúp đỡ người khác ngoài kia một ngày nào đó. Hãy đến lúc bạn làm việc về phát triển front-end, hãy nhớ rằng các giá trị datetime nằm trong GMT trong DB!