Правильный способ модификации enum в плагинах.

Проблема заключается в том, что некоторые плагины заменяют поле target_type таблицы comment, тем самым создавая свои новые типы комментариев, но затирая при этом уже добавленные. Разработчики упрощают себе жизнь, ограничиваясь строкой в dump.sql (пример из плагина «компании»)
ALTER TABLE `prefix_comment` 
	MODIFY target_type enum('topic','talk','company','clan') 
	DEFAULT 'topic';

В список риска попадает практически всё, где используется target_type enum: favourite, vote, comment_online.

При установки нескольких таких плагинов начинается бардак. Такие недоработки я заметил в следующих плагинах: «Компании», «Объявления», «Вопросы и ответы», «Места и события». Так делать нельзя. Программист разберется и исправит ошибку, но что делать обычным людям, далеким от php и sql, которые просто используют движок и несколько таких плагинов?

Тру кодером оказался Алексей Волков, разработчик «Комментариев для статических страниц». При установке плагина он в функции Activate проверяет target_type и добавляет новое поле только если его там нет, сохраняя при этом его старое содержимое. Не спросясь разрешения Алексея (надеюсь он меня простит — за правое дело радею) выкладываю часть кода, отвечающего за это.

$oDb = $this->Database_GetConnect();
$sql = 'SHOW COLUMNS FROM  `'.Config::Get('db.table.comment').'`';
$aRows = $oDb->select($sql);
foreach ($aRows as $aRow) {
	if ($aRow['Field'] == 'target_type') break;
}

if (strpos($aRow['Type'], "'page'") === FALSE)
{
	// - Вносим изменение в поле target_type в таблице prefix_comment
	$aRow['Type'] =str_ireplace('enum(', "enum('page',", $aRow['Type']);
	$sql = "ALTER TABLE `".Config::Get('db.table.comment')."` 
		CHANGE `target_type` `target_type` " . $aRow['Type'] . " 
		NOT NULL DEFAULT 'topic'";
	$oDb->query($sql);
} 


Уважаемые разработчики, не поленитесь обновить свои плагины и внести изменения.

Хотел опубликовать в тематическом блоге, например в «Дополнительные модули и доработки для LiveStreet», но видимо не хватает кармы, это мой первый пост/комментарий вообще на livestreet.ru

PS. в sql запросах типа ALTER проще использовать MODIFY вместо CHANGE, т.к. первый не требует указывать название поля два раза.

16 комментариев

avatar
пользуюсь похожей конструкцией еще с плагина livestreet.ru/blog/6030.html
public function Activate() {
		if (!$this->isFieldExists('user_soccom')) {
			$this->ExportSQL(dirname(__FILE__).'/dump.sql');
		}
    return true;
	}

	public function Init() {

  }

  protected function isFieldExists($sFieldName) {
		$sQuery="SHOW FIELDS FROM ".Config::Get('db.table.user');
    $return = false;
    if ($aRows=$this->Database_GetConnect()->select($sQuery)) {
      foreach ($aRows as $key => $aRow){
        if ($aRow['Field'] == $sFieldName){
          $return = true;
        }
      }
      return $return;
		}
		return false;
	}

еще, бы хорошо было бы чтобы использовали конструкцию типа
$a1 = Config::Get('block.rule_index_blog.blocks.right');
$a2 = array('adunits'=>array('params'=>array('plugin'=>'adunits'), 'priority'=>10));
Config::Set('block.rule_index_blog.blocks.right', array_merge ($a1, $a2));
для подключения блоков в слайдбар, ибо при установке нескольких плагинов пересекающиеся блоки могут затираться
avatar
Ну, проверка наличия поля, это всё-таки не проверка содержимого поля. Но тем не менее.

А вот слияние массивов блоков — я видел у тебя в адюнитах, когда разбирался с плагинами. Понравилось, использую.
avatar
Спасибо, это очень хорошее решение, сам над этим не раз задумывался но пока не мог нечего с этим сделать…
avatar
Об этом был разговор в личке у разработчиков. Проблема есть, но делать костыли не совсем правильно. Функционал проверки должен быть на стороне движка. Кто-то по-моему обещал добавить эту проверку на сторону движка.
avatar
Ну НЕ делать костыли, по-моему, еще более не правильно. С костылям-то еще как-то ходить можно, а без них… :) Так, что пока нет решения в движке — делаем костыли.
avatar
Видимо, хорошо было бы некоторые разговоры (или хотя бы их итоги) разработчиков в личке выкладывать на всеобщее обозрение. А то плагины платные, стоят денег, а такие вот косяки там на каждом шагу.
avatar
Это не косяки, и к платности плагинов это тем более не имеет никакого отношения. Это мелкие конфликты плагинов, которых в любом случае не избежать.
avatar
изменение enum поля в таблице комментов на жирном сайте (у меня было 200к комментов) встанет вам в пол часа отработки sql запроса. с учетом того, что таймаут на http-запрос обычно секунд 30.
лучше это делать из консоли.
avatar
Я не знаю что вы там за сервера используете для своих проектов, но такого быть не должно. 200к это вобщем-то не так уж и много.
avatar
Intel® Core(TM)2 Duo CPU E7500 @ 2.93GHz
а медленно из-за innodb, подозревается
avatar
150к+ с копейками комментариев. VPS за 30баксов. InnoDB ALTER TABLE отработал за время работы скрипта.

Тут либо вы цифру потолочную назвали. Либо очень плохо настроена СУБД для работы с InnoDB
avatar
ну не то чтобы потолочная, 15+ минут было точно.
есть кстати какие мануалы по настройке мускуля под innodb проверенные?
avatar
Не знаю, к сожалению. После того как были похожие проблемы с производительностью мы решили заплатить человеку за настройку )
avatar
вы заплатили за настройку и не спросили у него как он всё это сделал? (
avatar
mysql perfomance blog. а вообще я тюню под действием спидов mysqltuner.pl
avatar
Добавили в движок(Plugin) метод:
addEnumType($sTableName,$sFieldName,$sType)
  • ort
  • +1
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.