Entonces, después de pasar casi un día luchando con este mismo problema en mi propia extensión, pensé en compartir mi solución aquí. Algo a tener en cuenta es que mis entidades no están utilizando el sistema EAV, cada entidad tiene su propia tabla plana con una columna para cada atributo. Mi entidad tiene cuatro atributos de fecha y hora, dos de los cuales se rellenan a partir de la entrada del usuario ( open_date
, close_date
) y dos de los cuales se rellenan automáticamente con el código fuente ( create_date
, close_date
).
La clase de modelo de la entidad
En la clase de modelo de la entidad incluí lo siguiente:
- Una forma de definir y buscar qué atributos son del tipo datetime y se completan a través de los datos ingresados por el usuario suministrados en la hora local de la tienda.
- Un método que convierte solo estos campos de la hora GMT a la hora local de la tienda (más sobre esto más adelante).
- Un método _beforeSave () que establece los atributos 'edit_date' y 'create_date' (que no se completan a través de la entrada del usuario) en GMT para mí automáticamente al guardar.
El código fuente:
/**
* 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;
}
La acción saveAction del controlador administrativo de la entidad
En el método saveAction de mi controlador, utilicé el método getDateFields () definido en la clase de modelo para saber qué atributos necesito cambiar de la hora local de la tienda (que fue ingresada por el usuario) a la hora GMT antes de guardar en la base de datos. Tenga en cuenta que esto es solo un fragmento parcial de mi método de guardar:
....
$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();
....
El bloque de formulario de administrador para editar la entidad
A diferencia del widget de cuadrícula de administración de Magento, que espera que los valores de fecha y hora de las colecciones se suministren en GMT, con la intención de convertir estos valores a la hora local de la tienda antes de mostrar la página, el widget de formulario de administración de Magento no sigue este comportamiento. En cambio, el widget de formulario aceptará el valor de fecha y hora como es, y lo mostrará sin ajustar automáticamente la hora. Por lo tanto, dado que los valores se almacenan en la base de datos en GMT, primero debemos convertir nuestros atributos de fecha y hora ingresados por el usuario a la hora local de la tienda antes de suministrar esos datos al formulario. Aquí es donde entra en juego nuestro # 2 en la clase de modelo de la entidad .
Aquí hay una PORCIÓN del método _prepareForm () de la clase de bloque de mi formulario de administrador (que extiende Mage_Adminhtml_Block_Widget_Form). He omitido la mayoría de mi función, tratando de incluir solo el mínimo básico que es relevante para esta pregunta, y aún así proporcionar un método de clase válido:
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 mayor parte de esto sigue cualquier otro widget de formulario para Magento. Sin embargo, lo importante que es importante tener en cuenta aquí es que en lugar de llamar $form->setValues($model->getData())
, llamamos $form->setValues($model->getAdminFormData())
. Lo cual, si revisamos mi código desde el primer segmento de esta respuesta, este método requiere la conversión de todos los atributos de fecha y hora, que son ingresados por el usuario, de GMT a la hora local de la tienda.
Resultado final:
- Todos los valores guardados en DB en tiempo GMT.
- Los valores ingresados por el usuario se convierten de GMT a la hora local de la tienda, antes de darle el formulario de edición
- Admin Grid funciona como siempre, tomando los valores GMT y convirtiéndolos a la hora local de la tienda antes de mostrar la grilla en la página.
Espero que esto sea un recurso valioso para ayudar a alguien más algún día. Cuando llegue el momento de trabajar en el desarrollo front-end, tenga en cuenta que los valores de fecha y hora están en GMT en el DB.