Почему в modx не работает метод save() для существующего объекта? (РЕШЕНО)
Все привет! Подскажите, пожалуйста, почему метод save() не работает для существующего объекта, хотя для нового — работает?
Пробую так:
Схема:
При этом для соседних объектов работает прекрасно. И на новые, и на существующие. Хотя там всё аналогично.
Пробую так:
$test = $modx->getObject('LjValues', ['order_id' => 3, 'field_id' => 1]);
echo $test->get('value');
$test->set('value', "тестовый тест");
if($test->save() === true){
echo $test->get('value');
}
И всё как бы отлично, выводит сначала старое значение, потом в $test->save() === true, выводит новое значение. Но в базе остаётся старое, лог молчит.Схема:
<object class="LjValues" table="lj_values" extends="xPDOSimpleObject">
<field key="field_id" dbtype="int" precision="11" phptype="integer" null="false" />
<field key="value" dbtype="varchar" precision="191" phptype="string" null="false" />
<field key="order_id" dbtype="int" precision="11" phptype="integer" null="false" />
<aggregate alias="LjFields" class="LjFields" local="field_id" foreign="id" cardinality="one" owner="foreign" />
<aggregate alias="LjOrders" class="LjOrders" local="order_id" foreign="id" cardinality="one" owner="foreign" />
</object>
Пробовал убирать связи, менять на xPDOObject, не работает…При этом для соседних объектов работает прекрасно. И на новые, и на существующие. Хотя там всё аналогично.
Комментарии: 17
Боже, я не знаю почему, но LjValues — плохое название. Просто переименовал в LjFieldvalue — всё изумительно.
И таблицу в modx_lj_fieldvalue.
И таблицу в modx_lj_fieldvalue.
Можно проверять на true так:
if($test->save())
Если объект сохранится, то вернется true. А если вернется true, то if сработает
Он возвращал true, хотя объект не сохранялся, в этом и проблема. Я нашёл несколько подобных проблем в eng форумах, но тоже без решений адекватных. Не знаю почему, но именно название LjValues не понравилось xPDO. Даже если менял все поля таблицы — всё равно. Проблема именно в названии. Когда поменял его — всё заработало.
А таблицу пересоздавал заново или просто переименовал? Т.е. данные оставались старые?
Сначала создал копию с такой же структурой, но другим именем — сработало, удивился. Переименовал старую, обновил схему — и она заработала.
Смущает именно момент с тем, что newObject работал полностью — создавал, устанавливал значения, сохранял. getObject получал, set работал, но не сохранял. Самое странное, что save отдавал true…
Смущает именно момент с тем, что newObject работал полностью — создавал, устанавливал значения, сохранял. getObject получал, set работал, но не сохранял. Самое странное, что save отдавал true…
Просто первое, что бросается в глаза — это недоделанная структура таблицы. Именно поэтому возможны одинаковые записи. А так как getObject() получает только один объект, то вероятно, что он получает не тот объект, который ты проверяешь. А метод save() говорит, что объект обновлен и возвращает true. Просто это другой объект. Это самый вероятный сценарий при такой структуре таблицы.
Тоже думал об этом. Но нет, получал он именно тот объект, который я хотел (смотрел по значениям), уникальность именно по ['order_id' => 3, 'field_id' => 1]. Чистил таблицу, создавал 1 запись, её же получал и пытался редактировать — найн. Всё перепроверял на 1000 раз.
Да и в любом случае, как оно тогда могло заработать с другим именем таблицы, если структура осталась старой?
Да и в любом случае, как оно тогда могло заработать с другим именем таблицы, если структура осталась старой?
<object class="LjFieldvalue" table="lj_fieldvalue" extends="xPDOSimpleObject">
<field key="order_id" dbtype="int" precision="11" phptype="integer" null="false" />
<field key="field_id" dbtype="int" precision="11" phptype="integer" null="false" />
<field key="value" dbtype="varchar" precision="191" phptype="string" null="false" />
</object>
Могу попозже повторить, но не знаю как получить хоть какую-то информацию, чтобы зарепортить о баге. Ошибок не возникало никаких абсолютно на всех уровнях log_level
Я выше уже написал, что это не ошибка системы, а ошибка проектирования таблицы. В дальнейшем даже у новой модели может появится такая же проблема.
Если не составит труда, можете объяснить в чём проблема структуры?
Всю информацию заношу и получаю только по связке order_id и field_id. Каждое из этих полей может дублироваться, но двух объектов, у которых оба эти поля попарно равны — нет. Всё проверяю в сниппете, прежде чем занести.
Там суть, что нужно создавать таблицу, структура которой может расширяться по горизонтали -Fields (то, что выводится в header таблицы) и по вертикали — уже сами Orders (то, что создаёт ряды). А Values уже, соответственно, по пересечению горизонтального и вертикального.
p.s. извиняюсь, что на две ветки отвечать получилось.
Всю информацию заношу и получаю только по связке order_id и field_id. Каждое из этих полей может дублироваться, но двух объектов, у которых оба эти поля попарно равны — нет. Всё проверяю в сниппете, прежде чем занести.
Там суть, что нужно создавать таблицу, структура которой может расширяться по горизонтали -Fields (то, что выводится в header таблицы) и по вертикали — уже сами Orders (то, что создаёт ряды). А Values уже, соответственно, по пересечению горизонтального и вертикального.
p.s. извиняюсь, что на две ветки отвечать получилось.
Так а где в вашей таблице указано, что это primary/unique поля? Конкретно с вашей схемой в таблице может содержаться хоть 20 записей с одинаковыми значениями order_id и field_id. Добавьте индекс для этих полей, указав там, что это primary & unique (в случае с xPDOObject) или просто unique (в случае xPDOSimpleObject).
Так они и не unique.
Может быть такое:
order_id = 1 / field_id = 1
order_id = 1 / field_id = 2
order_id = 1 / field_id = 3
order_id = 2 / field_id = 1
order_id = 2 / field_id = 2
order_id = 2 / field_id = 3
Но не может быть такого:
order_id = 2 / field_id = 2
order_id = 2 / field_id = 2
Это проверяется на стороне сниппета при сохранении информации.
Или есть вариант делать unique именно по двум колонкам разом?
Может быть такое:
order_id = 1 / field_id = 1
order_id = 1 / field_id = 2
order_id = 1 / field_id = 3
order_id = 2 / field_id = 1
order_id = 2 / field_id = 2
order_id = 2 / field_id = 3
Но не может быть такого:
order_id = 2 / field_id = 2
order_id = 2 / field_id = 2
Это проверяется на стороне сниппета при сохранении информации.
Или есть вариант делать unique именно по двум колонкам разом?
Да, есть вариант делать unique по двум и более колонкам.
Лично я не вижу необходимости в этой схеме наследоваться от xPDOSimpleObject.
Используйте xPDOObject, указывайте эти 2 поля как primary & unique, добавив такой индекс
Лично я не вижу необходимости в этой схеме наследоваться от xPDOSimpleObject.
Используйте xPDOObject, указывайте эти 2 поля как primary & unique, добавив такой индекс
<index alias="PRIMARY" name="PRIMARY" primary="true" unique="true" type="BTREE">
<column key="order_id" length="" collation="A" null="false" />
<column key="field_id" length="" collation="A" null="false" />
</index>
Обновил ответ, изначально немного не так понял ваше сообщение.
Не может быть именно так:
order_id = 2 / field_id = 2
order_id = 2 / field_id = 2
Т.е. два объекта, у которых попарно равные order_id и field_id не могут существовать.
Не знал, что в одном индексе может быть несколько полей, посыпаю голову пеплом. Спасибо за полезный совет!
order_id = 2 / field_id = 2
order_id = 2 / field_id = 2
Т.е. два объекта, у которых попарно равные order_id и field_id не могут существовать.
Не знал, что в одном индексе может быть несколько полей, посыпаю голову пеплом. Спасибо за полезный совет!
При работе с xPDOObject будет полезно почитать еще это: modx.pro/development/1177
дабы не наступить на грабли
дабы не наступить на грабли
Как написал Артём, нужно делать индекс по этим полям (order_id и field_id). И лучше первичный ключ. А наследовать от xPDOObject.
В этом случае:
1. mySql будет следить, чтобы не было дублей.
2. Значительно ускорится выборка таких записей.
В этом случае:
1. mySql будет следить, чтобы не было дублей.
2. Значительно ускорится выборка таких записей.
Не знал, что в одном индексе может быть несколько полей, очень полезный совет оказался.
Завтра попробую проверить с такой схемой и всеми названиями, как были раньше. Посмотрю, проблема в этом, или всё-же в другом.
Завтра попробую проверить с такой схемой и всеми названиями, как были раньше. Посмотрю, проблема в этом, или всё-же в другом.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.