Почему в 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, не работает…

При этом для соседних объектов работает прекрасно. И на новые, и на существующие. Хотя там всё аналогично.
Овчинников Егор Эдуардович
modx.pro
191
0

Комментарии: 17

Боже, я не знаю почему, но LjValues — плохое название. Просто переименовал в LjFieldvalue — всё изумительно.
И таблицу в modx_lj_fieldvalue.
    Тимур
    22 февраля 2020, 13:31
    +1
    Можно проверять на true так:
    if($test->save())
    Если объект сохранится, то вернется true. А если вернется true, то if сработает
      Он возвращал true, хотя объект не сохранялся, в этом и проблема. Я нашёл несколько подобных проблем в eng форумах, но тоже без решений адекватных. Не знаю почему, но именно название LjValues не понравилось xPDO. Даже если менял все поля таблицы — всё равно. Проблема именно в названии. Когда поменял его — всё заработало.
        Сергей Шлоков
        23 февраля 2020, 13:49
        +1
        А таблицу пересоздавал заново или просто переименовал? Т.е. данные оставались старые?
          Сначала создал копию с такой же структурой, но другим именем — сработало, удивился. Переименовал старую, обновил схему — и она заработала.

          Смущает именно момент с тем, что newObject работал полностью — создавал, устанавливал значения, сохранял. getObject получал, set работал, но не сохранял. Самое странное, что save отдавал true…
            Сергей Шлоков
            23 февраля 2020, 14:16
            +1
            Просто первое, что бросается в глаза — это недоделанная структура таблицы. Именно поэтому возможны одинаковые записи. А так как 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
              Сергей Шлоков
              23 февраля 2020, 14:22
              +1
              Я выше уже написал, что это не ошибка системы, а ошибка проектирования таблицы. В дальнейшем даже у новой модели может появится такая же проблема.
                Если не составит труда, можете объяснить в чём проблема структуры?
                Всю информацию заношу и получаю только по связке order_id и field_id. Каждое из этих полей может дублироваться, но двух объектов, у которых оба эти поля попарно равны — нет. Всё проверяю в сниппете, прежде чем занести.

                Там суть, что нужно создавать таблицу, структура которой может расширяться по горизонтали -Fields (то, что выводится в header таблицы) и по вертикали — уже сами Orders (то, что создаёт ряды). А Values уже, соответственно, по пересечению горизонтального и вертикального.

                p.s. извиняюсь, что на две ветки отвечать получилось.
                  Артем
                  23 февраля 2020, 15:30
                  +1
                  Так а где в вашей таблице указано, что это 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 именно по двум колонкам разом?
                      Артем
                      23 февраля 2020, 16:22
                      1
                      +1
                      Да, есть вариант делать 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 не могут существовать.

                        Не знал, что в одном индексе может быть несколько полей, посыпаю голову пеплом. Спасибо за полезный совет!
                        Артем
                        23 февраля 2020, 16:32
                        +1
                        При работе с xPDOObject будет полезно почитать еще это: modx.pro/development/1177
                        дабы не наступить на грабли
                  Сергей Шлоков
                  23 февраля 2020, 16:18
                  +1
                  Как написал Артём, нужно делать индекс по этим полям (order_id и field_id). И лучше первичный ключ. А наследовать от xPDOObject.
                  В этом случае:
                  1. mySql будет следить, чтобы не было дублей.
                  2. Значительно ускорится выборка таких записей.
                    Не знал, что в одном индексе может быть несколько полей, очень полезный совет оказался.

                    Завтра попробую проверить с такой схемой и всеми названиями, как были раньше. Посмотрю, проблема в этом, или всё-же в другом.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      17