Closed matperez closed 9 years ago
Добавлю по русски. Есть модель airport
с полем name
. Для этого поля должен использоваться UniqueValidator. Если к нему же прикрутить MultilingualBehavior, то при сохранении модели получаю ошибку, что поле в целевой таблице не найдено. Естественно, поле name_ru и не должно присутствовать в таблице airport
. Судя по логам он пытается вызвать UniqueValidator для поля name_ru, хотя ничего такого в правилах модели не прописано.
Попробуйте кастомизировать unique валидатор
Здравствуйте!
Подскажите как именно это можно сделать? Написать свой? Я так понимаю, он не должен вызывать валидатор в таком виде. Этого атрибута ведь не существует в базе. Даже в таблице с переводами он прописан как просто name...
CREATE TABLE `airportLang` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`airportId` int(11) NOT NULL,
`language` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`description` text COLLATE utf8_unicode_ci,
PRIMARY KEY (`id`),
KEY `idx_airportLang_airport` (`airportId`),
CONSTRAINT `idx_airportLang_airport` FOREIGN KEY (`airportId`) REFERENCES `airport` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Валидаторы динамически применяются для всех переводов. Соотвественно, возникает проблема с уникальностью мультиязычных полей. Атрибут и не должен существовать в БД. Для реализации мультиязычности добавляются динамические атрибуты модели в виде attribute + _ + lang. Так как стандартный валидатор позволяет лишь дополнять запрос к БД, вам придется сделать свою реализацию, например в виде inline валидатора. Немного удивлен, что мультиязычные поля проверяют на уникальность...
Так я и не хочу проверять виртуальный атрибут на уникальность, его проверка сама собой возникает, если валидатор навешан на исходный атрибут (локализуемый). т.е. если в модели есть атрибут name и для него прописана проверка на уникальность, дополнительно в той же таблице базы проверяется уникальность виртуального атрибута name_en/name_ru, хотя никаких правил для него нет. Я так понял, что behavior где-то внутри метода configure пытается применить к виртуальным полям валидаторы исходных и как раз в случае unique validator это работает не совсем корректно.
Если топорно, то можно добавить исключение в код, который навешивает валидаторы, тогда все работает, но можно наверное как-то более красиво все сделать.
if ($rule[1] === 'unique') {
// do nothing
} elseif ($rule[1] !== 'required' || $this->forceOverwrite) {
if (isset($rule['skipOnEmpty']) && !$rule['skipOnEmpty'])
$rule['skipOnEmpty'] = !$this->forceOverwrite;
$validators[] = Validator::createValidator($rule[1], $owner, $attribute . '_' . $language, array_slice($rule, 2));
} elseif ($rule[1] === 'required') {
//We add a safe rule in case the attribute has only a 'required' validation rule assigned
//and forceOverWrite == false
$validators[] = Validator::createValidator('safe', $owner, $attribute . '_' . $language, array_slice($rule, 2));
}
Пофиксил в релизе 1.0.2
Looks like it's trying to apply UniqueValidator for virtual localized field.
I got following error trying to create new entry with localized attribute (name) that requires uniquenes
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'name_ru' in 'where clause' The SQL being executed was: SELECT * FROM
airport
WHEREname_ru
='Внуково' LIMIT 2Saving is successful if i comment
[['name'], 'unique'],
validator in model rules.