#php #mysql #joomla #transactions
#php #mysql #joomla #транзакции
Вопрос:
Я разрабатываю компонент календаря для Joomla 3.x. Я использую MySQL 5.5.32
В серверной части у меня есть форма для сохранения данных о событиях в базе данных и загрузки изображения.
Чтобы справиться с изображением, я расширяю JModelAdmin и переопределяю функцию сохранения.
public function save($data)
{
[...]
$db = $this->getDbo();
try
{
$db->transactionStart();
// Move uploaded image in correct folder
if($image = FileUtility::preprocessJFormFile('image', '/images/aftevents/'))
{
$fileExtension = JFile::getExt($image);
// register the image extension to be saved in the database
$data['image_ext'] = $fileExtension;
}
if (parent::save($data))
{
// Rename image with event id
if($image)
{
$id = $data['id'] ? $data['id'] : $this->getState($this->getName().'.id', 0);
if(!$id)
{
throw new Exception('COM_AFTEVENTS_EXCEPTION_NO_ID', 1502);
}
$finalImage = JPATH_ROOT.'/images/aftevents/'. $id .'.'. $fileExtension;
JFile::move($image, $finalImage);
// Create thumbnails
$params = JComponentHelper::getParams('com_aftevents');
$params->toArray();
$IEWidth = $params['image_event_width'];
$IEHeight = $params['image_event_height'];
$ICWidth = $params['calendar_image_event_width'];
$ICHeight = $params['calendar_image_event_height'];
$jimage = new JImage($finalImage);
$thumbs = $jimage->createThumbs(array($IEWidth.'x'.$IEHeight, $ICWidth.'x'.$ICHeight), 5);
}
$db->transactionCommit();
return true;
}
}
catch (Exception $e)
{
// catch any database errors.
$db->transactionRollback();
$this->setError($e->getMessage());
return false;
}
return false;
}
Теперь транзакция не работает. Если перехватывается исключение, вставка в базу данных не откатывается.
Я полагаю, это связано с тем, что инструкции по транзакции и вставка базы данных не вызываются одним и тем же объектом JDatabaseDriver или где-то в родительских классах используется другая транзакция, когда запись сохраняется в базе данных, и это портит эту.
Кто-нибудь знает, как заставить мою транзакцию работать?
Комментарии:
1. Итак, ваша идея состоит в том, чтобы обернуть вызываемый родительский save() в транзакцию, а также в try catch? Имейте в виду, что вы не передаете $ db родительскому элементу и что сам родительский элемент не выполняет запрос на обновление, который выполняется в классе JTable. Я бы сказал, что вы могли бы сделать, это в вашем классе table предоставить метод store (), который включает поддержку транзакций.
2. Я понимаю вашу точку зрения. Я собираюсь попробовать это и сообщить вам. Дело в том, что не имеет особого смысла иметь дело с изображением в классе Jtable.
3. Ваша цель не сохранить запись, если загрузка не работает? В этом случае я бы выполнил загрузку перед save() .
4. Мой скрипт заботится о загрузке файла перед вставкой в базу данных. После этого мне нужно переименовать файл с идентификатором события и создать несколько эскизов. Я мог бы сделать это перед обновлением, но для вставки я должен сделать это после, чтобы получить идентификатор, сгенерированный автоинкрементом в базе данных.
5. Хорошо, я сделал то, что хотел, скопировав полную функцию сохранения класса JModelAdmin непосредственно в мой подкласс и адаптировав приведенный выше код. У меня действительно есть доступ к нужному объекту JTable в этой функции. Это немного грязно, но работает.
Ответ №1:
Транзакции могут использоваться только с механизмом хранения, поддерживающим транзакции, таким как InnoDB. Все основные таблицы Joomla используют InnoDB, однако сторонние расширения не могут. Проверьте это перед использованием транзакций.
Измените механизм хранения таблиц на InnoDB.