MODX Revolution и MySQL v5.7.x: проблема с сохранением значений TV-параметров

Работая с новым сайтом на движке MODX Revolution я столкнулся с проблемой невозможности сохранения значений пользовательских TV-параметров. Как оказалось, всему виной была новая версия MySQL.



Суть проблемы

Во время сохранения ресурса значения TV-параметров не сохраняются в таблице базы данных (modx_site_tmplvar_contentvalues), при этом внешне всё выглядит нормально: после сохранения в соответствующих полях отображаются обновлённые значения. Однако после перезагрузки страницы редактирования поля вновь оказываются пустыми (или заполненными значениями по умолчанию).

В файле error.log системы (раздел Управление→Отчёты→Журнал ошибок административной панели) отображается следующее сообщение об ошибке:

[2016-10-19 08:18:19] (ERROR @ /var/www/init/www/core/xpdo/om/xpdoobject.class.php : 240) Error HY000 executing statement: 
Array
(
    [0] => HY000
    [1] => 3065
    [2] => Expression #1 of ORDER BY clause is not in SELECT list, references column 'init.tvtpl.rank' which is not in SELECT list; this is incompatible with DISTINCT
)

Версия MODX Revolution: 2.5.0-pl

Версия MySQL: 5.7.15

Причина

Потратив приличное количество времени на поиск решения в интернете, я узнал, что всё дело в новой версии MySQL и её обновлённых настройках по умолчанию: задействована настройка ONLY_FULL_GROUP_BY, в результате чего перестаёт работать часть запросов MODX. Как оказалось, проблема уже известна разработчикам (описание в багтрекере MODX на GitHub: https://github.com/modxcms/revolution/issues/12826) и будет исправлена в новых версиях движка (скорее всего в версии 2.5.2-pl).

Решение

Чтобы не ждать официального релиза с исправлениями и обновлять движок, вы можете самостоятельно внести правки в файлы ядра MODX, к счастью исправлять придётся немного:

  • Файл /core/model/modx/modresource.class.php:
    		$c = $resource->xpdo->newQuery('modTemplateVar');
    		$c->query['distinct'] = 'DISTINCT';
    		$c->select($resource->xpdo->getSelectColumns('modTemplateVar', 'modTemplateVar'));
    		$c->select($resource->xpdo->getSelectColumns('modTemplateVarTemplate', 'tvtpl', '', array('rank')));
    		if ($resource->isNew()) {
    			$c->select(array(
    					'modTemplateVar.default_text AS value',

    Добавлена строка №342.

  • Файл /core/model/modx/modtemplate.class.php:
    			$c = $this->xpdo->newQuery('modTemplateVar');
    			$c->query['distinct'] = 'DISTINCT';
    			$c->select($this->xpdo->getSelectColumns('modTemplateVar'));
    			$c->select($this->xpdo->getSelectColumns('modTemplateVarTemplate', 'tvtpl', '', array('rank')));
    			$c->select(array('value' => $this->xpdo->getSelectColumns('modTemplateVar', 'modTemplateVar', '', array('default_text'))));
    			$c->innerJoin('modTemplateVarTemplate','tvtpl',array(
    				'tvtpl.tmplvarid = modTemplateVar.id',

    Добавлена строка №144.

После внесения изменений механизм сохранения значений TV-параметров должен работать нормально.

Скажу ещё, что можно просто отказаться от использования MySQL последней версии, однако не думаю, что такой способ решения проблемы придётся вам по душе.