Nachdem ich fast einen Tag damit verbracht hatte, mit demselben Problem in meiner eigenen Erweiterung zu kämpfen, dachte ich, ich würde meine Lösung hier teilen. Zu beachten ist, dass meine Entitäten das EAV-System nicht verwenden. Jede Entität verfügt über eine eigene flache Tabelle mit einer Spalte für jedes Attribut. Meine Entität verfügt über vier Datums- / Uhrzeitattribute, von denen zwei aus Benutzereingaben ( open_date
, close_date
) und zwei automatisch aus dem Quellcode ( create_date
, close_date
) ausgefüllt werden .
Die Modellklasse der Entität
In die Modellklasse der Entität habe ich Folgendes aufgenommen:
- Eine Möglichkeit, zu definieren und abzurufen, welche Attribute vom Typ datetime sind und über vom Benutzer eingegebene Daten in der Ortszeit des Geschäfts ausgefüllt werden.
- Eine Methode, die nur diese Felder von der GMT-Zeit in die Ortszeit des Geschäfts konvertiert (dazu später mehr).
- Eine _beforeSave () -Methode, die die Attribute 'edit_date' und 'create_date' (die nicht über Benutzereingaben ausgefüllt werden ) in GMT für mich beim Speichern automatisch festlegt .
Der Quellcode:
/**
* 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;
}
Die saveAction des Admin Controllers der Entität
In der saveAction-Methode meines Controllers habe ich die in der Modellklasse definierte getDateFields () -Methode verwendet, um zu wissen, welche Attribute ich von der Ortszeit des Geschäfts (die vom Benutzer eingegeben wurde) zur GMT-Zeit ändern muss, bevor ich sie in der Datumsbasis speichere. Beachten Sie, dass dies nur ein Teil meiner Speichermethode ist:
....
$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();
....
Der Admin-Formularblock zum Bearbeiten der Entität
Im Gegensatz zum Admin-Grid-Widget von Magento, das erwartet, dass Datums- / Uhrzeitwerte aus Sammlungen in GMT bereitgestellt werden, mit der Absicht, diese Werte vor dem Anzeigen der Seite in die Ortszeit des Geschäfts zu konvertieren, folgt das Admin-Formular-Widget von Magento diesem Verhalten nicht. Stattdessen akzeptiert das Formular-Widget den Datum / Uhrzeit-Wert unverändert und zeigt ihn an, ohne die Zeit automatisch anzupassen. Da die Werte in GMT in der Datenbank gespeichert sind, müssen wir zuerst die vom Benutzer eingegebenen datetime-Attribute in die Ortszeit des Geschäfts konvertieren, bevor wir diese Daten an das Formular senden. Hier kommt unsere Nummer 2 in der Modellklasse von The Entity ins Spiel.
Hier ist ein TEIL der _prepareForm () -Methode der Blockklasse meines Administratorformulars (die Mage_Adminhtml_Block_Widget_Form erweitert). Ich habe den größten Teil meiner Funktion weggelassen und versucht, nur das absolute Minimum einzubeziehen, das für diese Frage relevant ist, und trotzdem eine gültige Klassenmethode bereitzustellen:
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();
}
Das meiste davon folgt jedem anderen Formular-Widget für Magento. Das Wichtigste, was hier zu beachten ist, ist jedoch, dass $form->setValues($model->getData())
wir nicht anrufen , sondern anrufen $form->setValues($model->getAdminFormData())
. Wenn wir meinen Code aus dem ersten Segment dieser Antwort überprüfen, konvertiert diese Methode alle vom Benutzer eingegebenen Datums- / Uhrzeitattribute von GMT in die Ortszeit des Geschäfts.
Endresultat:
- Alle Werte werden in GMT-Zeit in der DB gespeichert.
- Vom Benutzer eingegebene Werte werden von GMT in die Ortszeit des Speichers konvertiert, bevor das Formular bearbeitet wird
- Das Admin-Raster funktioniert wie immer, nimmt GMT-Werte auf und konvertiert in die Ortszeit des Geschäfts, bevor das Raster auf der Seite gerendert wird.
Ich hoffe, dies ist eine wertvolle Ressource, um eines Tages jemand anderem da draußen zu helfen. Wenn Sie an der Front-End-Entwicklung arbeiten, denken Sie daran, dass die Datums- / Uhrzeitwerte in der Datenbank in GMT angegeben sind!