Quindi, dopo aver trascorso quasi un giorno a combattere con lo stesso problema nella mia estensione, ho pensato di condividere la mia soluzione qui. Qualcosa da notare è che le mie entità non stanno utilizzando il sistema EAV, ogni entità ha la sua tabella piatta con una colonna per ogni attributo. La mia entità ha quattro attributi datetime: due dei quali sono compilati dall'input dell'utente ( open_date
, close_date
) e due dei quali sono popolati automaticamente dal codice sorgente ( create_date
, close_date
).
La classe modello dell'entità
Nella classe del modello dell'entità ho incluso quanto segue:
- Un modo per definire e recuperare quali attributi sono di tipo datetime e vengono popolati tramite i dati immessi dall'utente forniti nell'ora locale del negozio.
- Un metodo che converte solo questi campi dall'ora GMT all'ora locale del negozio (ne parleremo più avanti).
- Un metodo _beforeSave () che imposta gli attributi 'edit_date' e 'create_date' (che non sono popolati dall'input dell'utente) in GMT per me automaticamente al salvataggio.
Il codice sorgente:
/**
* 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;
}
L'azione save del controller di amministrazione dell'entità
Nel metodo saveAction del mio controller, ho utilizzato il metodo getDateFields () definito nella classe del modello per sapere quali attributi devo cambiare dall'ora locale del negozio (che era stata immessa dall'utente) all'ora GMT prima di salvare nella base di date. Nota che questo è solo uno snippit parziale del mio metodo di salvataggio:
....
$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();
....
Admin Form Block per la modifica dell'entità
A differenza del widget della griglia di amministrazione di Magento, che prevede valori datetime dalle raccolte da fornire in GMT, con l'intenzione di convertire questi valori nell'ora locale del negozio prima di visualizzare la pagina, il widget del modulo di amministrazione di Magento non segue questo comportamento. Il widget del modulo accetterà invece il valore datetime così com'è e lo visualizzerà senza regolare automaticamente l'ora. Pertanto, poiché i valori sono memorizzati nel database in GMT, dobbiamo prima convertire gli attributi datetime immessi dall'utente nell'ora locale del negozio prima di fornire tali dati al modulo. È qui che entra in gioco la nostra classe n. 2 su The Entity's Model Class .
Ecco una PORZIONE del metodo _prepareForm () della classe di blocco del mio modulo di amministrazione (che estende Mage_Adminhtml_Block_Widget_Form). Ho omesso la maggior parte della mia funzione, cercando di includere solo il minimo indispensabile per questa domanda e fornire comunque un metodo di classe valido:
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();
}
La maggior parte di ciò segue qualsiasi altro widget di modulo per Magento. Tuttavia, l'unica cosa chiave che è importante notare qui è che anziché chiamare $form->setValues($model->getData())
chiamiamo $form->setValues($model->getAdminFormData())
. Che, se esaminiamo il mio codice dal primo segmento di questa risposta, questo metodo richiede di convertire tutti gli attributi datetime, immessi dall'utente, dal GMT all'ora locale del negozio.
Risultato finale:
- Tutti i valori salvati nel DB nell'ora GMT.
- I valori immessi dall'utente vengono convertiti da GMT all'ora locale del negozio, prima di inviarlo per la modifica del modulo
- Admin Grid funziona come sempre, prendendo i valori GMT e convertendoli nell'ora locale del negozio prima di eseguire il rendering della griglia sulla pagina.
Spero che questo si dimostri una risorsa preziosa per aiutare qualcun altro là fuori un giorno. Vieni ora che lavori allo sviluppo front-end, tieni presente che i valori di datetime sono in GMT nel DB!