Проблема с TV параметрами в MODx

$modx -> resource -> setTVValue(11, 1);

print_r($modx -> resource -> getTVValue(11));

$modx -> resource -> setTVValue(11, 2);

print_r($modx -> resource -> getTVValue(11));

That code outputs 2 and 2, when must outputs 1 and 2, the whole code is in the snippet, resource cache is turned off, snippet call is not cacheble too, like "[[!..."

Переводить не стал, думаю ты язык знаешь, вот тот же вопрос на stackoverflow.com/questions/14052207/modx-revo-settvvalue-returns-old-data
Yan Alex
27 декабря 2012, 09:23
modx.pro
1
11 044
0

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

Василий Наумкин
27 декабря 2012, 13:39
0
Быстро подорвался и на вапрос атветил, да?
    Yan Alex
    27 декабря 2012, 13:45
    0
    Тогда предлагаю добавить в форму вопроса поле «Волшебное слово» xD. Помочь сможешь? Пожаааалуйста )
      Василий Наумкин
      27 декабря 2012, 14:55
      1
      0
      Да хоть бы код в тег code оформил, хрен с ним, с «пожалуйста».
      Работает без проблем, но только при одном условии — если вызывается не на странице, ТВ которой он должен обновить.
      if ($res = $modx->getObject('modResource', 1)) {
      	$res->setTVValue(1, 1);
      	echo $res->getTVValue(1);
      
      	$res->setTVValue(1, 2);
      	echo $res->getTVValue(1);
      	die;
      // 12
      }

      А вот так — выдаёт прикольный глюк, очевидно связанный с кэшированием.
      if ($res = $modx->getObject('modResource', $modx->resource->id)) {
      	$res->setTVValue(1, 1);
      	echo $res->getTVValue(1);
      
      	$res->setTVValue(1, 2);
      	echo $res->getTVValue(1);
      	die;
      // 22
      }
      Поэтому, переходим на обычный xPDO
      if ($tv = $modx->getObject('modTemplateVarResource', array('tmplvarid' => 1, 'contentid' => $modx->resource->id))) {
      	$tv->set('value', 1);
      	echo $tv->get('value');
      	//$tv->save(); //по желанию
      		
      	$tv->set('value', 2);
      	echo $tv->get('value');
      	die;
      // 12
      }

      Почему выходит такая фигня — мне не ведомо, а копать исходники времени нет.
        Andrey Grachov
        27 декабря 2012, 15:00
        0
        В ходе обработки запроса modx загружает ресурс и все его tv-параметры, и потом при получении значений tv-параметров обращается к первоначальным данным. После установки нового значения надо выполнить что-то вроде:
        $modx->resource->set('tv_name', null);
          Yan Alex
          27 декабря 2012, 15:06
          0
          А можно полный код, а то я не понял к какому варианту применимо.
            Andrey Grachov
            27 декабря 2012, 15:13
            0
            После этой строки вашего первоначального кода:
            $modx->resource->setTVValue(11, 1);
            надо добавить
            $modx->resource->set('tv_name', null);
            или
            $tv = $modx->resource->get('tv_name');
            if (is_array($tv)) {
            	$tv[1] = 1;
            	$modx->resource->set('tv_name', $tv);
            }
            где tv_name — имя tv-параметра с id равным 11. Это позволит дальше на странице использовать новое значение tv-параметра, если оно необходимо.
              Yan Alex
              27 декабря 2012, 15:16
              0
              Хороший хак, спасибо, это позволит не уходить от стандартного АПИ модэкса, но как говорил Безумкин — выглядит не очень красиво, но думаю да и Х* с ним, хотя я сам тот еще эстет в этом плане )
                Василий Наумкин
                27 декабря 2012, 15:29
                0
                А как сохранить новое значение в ТВ?

                $modx->resource->save() не помогает, конечно. А если значение нужно только на время работы скрипта, и сохранять его не надо — то и ТВ ни к чему, можно любое имя написать.
                  Andrey Grachov
                  27 декабря 2012, 16:24
                  0
                  Сохранить новое значение стандартным способом:
                  $modx->resource->setTVValue(.., ...);
                  тот код просто использовать вдобавок, чтобы обновить значение у текущего ресурса modx, на время обращения к нему.
                    Василий Наумкин
                    27 декабря 2012, 16:26
                    0
                    Ну да, точно =)

                    Спасибо за новый способ работы с ТВ.
                      Yan Alex
                      27 декабря 2012, 16:31
                      0
                      Спасибо так же и от меня, чувствую сэкономили вы мне часов эдак n*999
                        Yan Alex
                        27 декабря 2012, 16:32
                        0
                        А так же интересно узнать откуда инфа по столь завуалированным нюансам? Почитать думаю не вредно будет.
                          Andrey Grachov
                          28 декабря 2012, 00:38
                          0
                          Лучший источник информации — исходный код :) Сам просто сталкивался с такой ситуацией и пришлось покопаться, чтобы дойти до истины.
                            Yan Alex
                            28 декабря 2012, 09:49
                            0
                            Ясно, я так делал, только пока язык учил, сейчас желания лезть в чужой код отпало на совсем — это очень много времени съедает, поэтому стараюсь использовать продукты которые не требуют чтобы кроме их непосредственных вохможностей была необходимость перелопачивать код, считаю такие продукты на уровне нашего автопрома, купил и ковыряйся )))
                  Василий Наумкин
                  27 декабря 2012, 15:09
                  0
                  Да, так и есть. А выводит он 22 потому, что 2 было сохранено в прошлый раз.
                  Если по очереди комментировать вызовы setTVValue — хорошо видно.

                  А ваш хак отлично работает, хоть и выглядит это некрасиво.
                  if ($res = $modx->getObject('modResource', $modx->resource->id)) {
                  	$modx->resource->set('test', null);
                  	$res->setTVValue(1, 1);
                  	echo $res->getTVValue(1);
                  
                  	$modx->resource->set('test', null);
                  	$res->setTVValue(1, 2);
                  	echo $res->getTVValue(1);
                  	die;
                  //12
                  }
                    Andrey Grachov
                    27 декабря 2012, 15:16
                    0
                    Чуть выше привел более эстетичное решение. Какое бы оно некрасивое не было, без него страница не увидит новое значения tv-параметра, если оно будет изменено, к примеру, сниппетом :)
                      Yan Alex
                      27 декабря 2012, 15:51
                      0
                      В моем случае помогло вот такое ваше решение.

                      $modx->resource->set('nodeShop_orderState', null);
                      		$modx->resource->set('nodeShop_orderData', null);
                      
                      		$result = array(
                      			$this -> resource -> setTVValue('nodeShop_orderState', json_encode($orderState)),
                      			$this -> resource -> setTVValue('nodeShop_orderData', json_encode($orderData))
                      		);
                      
                      		if(array_sum($result) != 2) return;
                        Yan Alex
                        27 декабря 2012, 15:52
                        0
                        После

                        $modx->resource->set('nodeShop_orderState', null);
                        $modx->resource->set('nodeShop_orderData', null);
                        Тв сразу же актуальны.
                    Илья Ершов
                    26 марта 2015, 16:31
                    0
                    Спасибо тебе огроменное Андрей, спустя 3 года!.. У меня сейчас из-за этого глюка чуть мозг не взорвался ))
                    Yan Alex
                    27 декабря 2012, 15:04
                    0
                    Да да, первый вариант, как раз вызывается на той самой странице, которую должен обновить, второй вариант, глючит, а третий вот как раз ждал от вас, спасибки огромное, он работает! Как в воду глядел, хотел на чистом xPDO написать. Кстати я еще нашел такой вариант, учудил тип с форума
                    $modx->resource->set('SendTestEmail', $fields);
                    у него такая же проблема была Ссылка на ветку, главное что во первых работает, но во вторых непонятно где он хранит эти данные у объекта, облазив БД не нашел никаких значений даже близко, что думаешь об этом методе?
                      Василий Наумкин
                      27 декабря 2012, 15:12
                      0
                      Судя по тому, что пишет Боб Рей — оно сохраняется в ТВ, а не в объект.
                        Yan Alex
                        27 декабря 2012, 15:14
                        0
                        Вот и я так думал пока не залз в БД и не увидел что там НЕТ этого значения =). Что то огонь какой то с этим API у них.
                          Василий Наумкин
                          27 декабря 2012, 15:23
                          0
                          У меня оно и не сохраняется.

                          Это поле будет работать только во время выполнения скрипта. То есть, методом set мы выставляем любое поле с любым значением, потом можем его использовать как хотим, а после работы оно пропадает — ибо сохранить его некуда, в модели то его нет.

                          Если же ничего туда не писать, а просто print_r($modx->resource->get('test')); — то будут данные ТВ параметра.

                          Всё это очень интересно, но мне надо работать, так что не буду копать «почему всё именно так, а не иначе». Вообще, стараюсь не использовать ТВ, если это возможно.
                            Yan Alex
                            27 декабря 2012, 15:26
                            0
                            Странно я проверял, потому что тоже думал что будет во время выполнения скрипта, и у меня писалось, то есть сперва я выставлял через сет а потом брал через гет закомментировав сет и у меня все показывалось как будто значение сохранилось.
                              Василий Наумкин
                              27 декабря 2012, 15:31
                              0
                              Ну — щас через админку смотрел, не сохраняется.

                              Хотя, уже ничему не удивлюсь =)
                                Yan Alex
                                27 декабря 2012, 15:42
                                0
                                Блин, да это мой косяк, извиняюсь, глаз замылился, действительно это атрибут на время выполнения скрипта. Видимо Боб до сих пор мучается =)
                  Yan Alex
                  27 декабря 2012, 13:54
                  0
                  Пробовал так, тот же результат, ТВ упорно меняется только после того как я один раз открою страницу, как будто тв у объекта сейвятся после отработки скрипта.

                  $tv = $modx->getObject('modTemplateVar',array('id'=>'11'));
                  $tv -> setValue($modx->resource->get('id'), 88);
                  $tv->save();

                  print_r($modx -> resource -> getTVValue(11));

                  Выводит сперва значение которое было, после перезагрузки страницы уже то что выставляю в скрипте.
                    Denys Butenko
                    27 декабря 2012, 15:08
                    0
                    Попробуй сниппет вызывать плагином до рендера страницы
                      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                      28