Наверх

Часть 3. Методы set и save

Продолжим серию статей об xPDO для начинающих. В предыдущих частях мы узнали, как можно получить значение полей того или иного объекта или даже нескольких объектов. Теперь посмотрим, как мы можем изменять эти значения.

Помимо метода get(), который получает значение, есть еще и метод set(), который это значение устанавливает. Мы можем поменять подряд сразу несколько значений, но после всех вызовов set() нужно объект сохранить. Сохраняет объект метод save().
set() — устанавливает значение одного из полей объекта.
save() — сохраняет все изменения в объекте.

Мы можем изменить ресурс прямо из консоли, вот так:
$res = $modx->getObject('modResource',22);
$res->set('pagetitle', 'Новости сайта');
$res->save();
После выполнения этого кода, заголовок ресурса будет «Новости сайта». Как видите, чтобы что-то делать с объектом, нам нужно его сначала получить. Если нам нужно внести изменения в несколько объектов, мы можем воспользоваться методом getCollection():
$titles = array(
        '1' => 'Главная'
      , '6' => 'О нас'
      , '8' => 'Галерея'
      , '11' => 'Контактная информация'
      , '22' => 'Новости компании'
    );
$resources = $modx->getCollection('modResource',array('parent' => 0));
foreach ($resources as $id => $res) {
    if (!$titles[$id]) continue;
    $res->set('pagetitle', $titles[$id]);
    $res->set('longtitle', $titles[$id]);
    $res->set('menutitle', $titles[$id]);
    $res->set('hidemenu', 0);
    $res->save();
}
Как видите, save() вызывается после всех set(), однако для каждого объекта. Ведь нам надо каждый объект сохранить.

Порой неудобно перечислять все поля, которые мы хотим изменить, да и код у нас становится нечитаемым. Можно, конечно, сделать так:
$titles = array(
    '1' => 'Главная'
  , '6' => 'О нас'
  , '8' => 'Галерея'
  , '11' => 'Контактная информация'
  , '22' => 'Новости компании'
);
$resources = $modx->getCollection('modResource',array('parent' => 0));
foreach ($resources as $id => $res) {
    if (!$titles[$id]) continue;
    $fields = array(
        'pagetitle' => $titles[$id]
      , 'longtitle' => $titles[$id]
      , 'menutitle' => $titles[$id]
      , 'hidemenu'  => 0
    );
    foreach ($fields as $field => $val) {
        $res->set($field, $val);
    }
    $res->save();
}
Но это необязательно — разработчики xPDO о нас позаботились и добавили метод fromArray(), который выполняет вышеприведенный код.
fromArray() — по анологии с методом toArray() (который получает все значения в виде массива) устанавливает значения, перечисленные в массиве
$titles = array(
    '1' => 'Главная'
  , '6' => 'О нас'
  , '8' => 'Галерея'
  , '11' => 'Контактная информация'
  , '22' => 'Новости компании'
);
$resources = $modx->getCollection('modResource',array('parent' => 0));
foreach ($resources as $id => $res) {
    if (!$titles[$id]) continue;
    $fields = array(
        'pagetitle' => $titles[$id]
      , 'longtitle' => $titles[$id]
      , 'menutitle' => $titles[$id]
      , 'hidemenu'  => 0
    );
    $res->fromArray($fields);
    $res->save();
}

Как видите, ничего сложного нет. Теперь небольшое практическое задание по пройденной теме:
Задание. Представьте, что вы сделали клиенту сайт, он его заполнил, в раздел «Статьи» уже выложил около 50 статей, после чего звонит вам и просит, чтобы в разделе статьи URL были такими:
/articles/23/
то есть, чтобы псевдонимом у статей был id ресурса. Напишите код, который надо выполнить в консоли, чтобы у всех существующих статей исправить псевдонимы.

Для более продвинутых пользователей — напишите плагин, который будет устанавливать нужное значение для всех создаваемых документов в разделе «Статьи»
Подсказка для тех, кто еще ни разу не писал своих плагинов
Решение задания

Оригинал статьи: community.modx-cms.ru/blog/modx-xpdo/10264.html G+


16 комментариев

  1. Evgeny Epifanov 01 ноября 2013, 13:20(Комментарий был изменён) # 0
    А как можно частично заменить эти значения?
    Пример:
    Копия Док1
    Копия Док2
    Копия Док3
    Копия Док4
    нужно заменить на:
    Док1
    Док2
    Док3
    Док4
    1. Илья Уткин 01 ноября 2013, 13:32(Комментарий был изменён) # 0
      Как-то так…
      $resources = $modx->getCollection('modResource',array('parent' => 12));
      foreach ($resources as $res) {
        $pagetitle = str_replace('Копия ','',$res->get('pagetitle'));
        $res->set('pagetitle',$pagetitle);
        $res->save();
      }
      1. Evgeny Epifanov 01 ноября 2013, 13:53(Комментарий был изменён) # 0
        Просто огроменное СПАСИБО!
        То, что нужно.
        1. Илья Уткин 01 ноября 2013, 14:05(Комментарий был изменён) # 0
          Но лучше бы вы, конечно, прочитали этот урок внимательнее и попытались сами написать код)))
    2. PticaOgnennaya 21 августа 2015, 09:11 # 0
      Стоит не забывать отчищать кэш ModX после внесения изменений, иначе вывод не изменится.
      1. Rosherh 15 февраля 2017, 13:01 # +1
        Простое задание, конечно можно было сюда сразу взять у родителя алиас и сделать конкатенацию, например. $parentAlias. '/'. $res_id, чтобы самому статически не указывать 'articles/, но для упрощения сделал так:

        
        <?php
        $output = '';
        
        $collection = $modx->getCollection('modResource', ['parent' => $id]);
        
        foreach($collection as $id => $obj) {
            $obj->set('alias', 'articles/' . $id);
            $obj->save();
        }
        
        
        Задание со *, пишем свой плагин и вешаем его на событие OnDocFormSave:

        <?php
        switch($modx->event->name) {
            case 'OnDocFormSave':
                    if ($resource->get('parent') == $id_parent) {
                        $resource->set('alias', 'article/' . $resource->get('id'));
                    }
                break;
        }
        Чтобы повесить плагин на данной событие нужно перейти во вкладку «Системные события» (ModX Revo v.2.5.4)
        1. Егор Морозов 28 марта 2017, 18:07 # 0
          Каким образом можно получить ID только что созданного объекта?
          При создании с помощью mysql можно использовать функцию mysql_insert_id();
          Нужен аналог для получения ID только что созданного объекта.

          Заранее спасибо :)
          1. Future 29 марта 2017, 02:10 # 0
            $obj->save();
            echo     $obj->id;
            
            1. Егор Морозов 29 марта 2017, 12:03 # 0
              Благодарю Вас! :)
          2. Дмитрий 30 марта 2017, 14:25 # 0
            <?php
            $res = $modx->getObject('modResource',7);
            $res->set('id', 15);
            $res->save();
            $output = $res->toArray();
            print "<pre>";
            print_r($output);
            
            Добрый день. Пытаюсь изменить ID ресурса. Console выводит, что ID поменялся. По факту — это не так.
            Что делаю не так
            P. S. Как только удаляю строку
            $res->set('id', 15);

            Console возвращает ID 7.
            P. S.S
            При изменении других полей ресурса, изменения сохраняются.
            1. Илья Уткин 08 апреля 2017, 08:39 # 0
              Да, по-моему, с полем id не всё так просто. Всё-таки это первичный ключ. Придётся придумать какое-то другое решение задачи)
              1. man 11 апреля 2017, 20:30 # 0
                А зачем Вам менять id ресурса?
                Серьезно, очень интересно…
                1. Дмитрий 11 апреля 2017, 20:36 # 0
                  Та Вы знаете, как выяснилось через 20 мин, после того как я этот комент отставил, стало не зачем =)
                  Ситуация была в следующем:
                  При помощи PDO Tools вытаскивал несколько дочерних ресурсов. Потом возникла необходимость последний ресурс при выдачи поставить на место второго. И почему-то начал копать в сторону смены Id, хотя стоило сразу разобраться в сортировке. Собственно задачу решил, а вопрос остался открытым )
              2. Станислав Однолетко 12 июля 2017, 14:07 # 0
                $getResource = $modx->getCollection('modResource',array('parent'=>'10'));
                foreach($getResource as $key=>$get){
                    $alias=$get->get('alias');
                    $alias=$get->set('alias','/article/'.$key);
                    $alias=$get->save();
                }
                1. Paul Abdullaev 18 декабря 2017, 20:34 # 0
                  Здравствуйте! Не знаю в тему или нет вопрос. Есть меню(свое, не через wayfinder или др. плагин). Имеет 3-й уровень вложенности (т.е. раздел-подраздел-подподраздел). Не включает главную страницу. Как сделать вывод URL страницы(*alias) в зависимости от пункта меню(*menutitle)? Причем желательно чтобы можно было менять menutitle на цифры, и в зависимости от этих цифр выдавать уже сам URL. Подскажите в какую сторону копать…
                  1. Илья Уткин 08 января 2018, 14:55 # 0
                    Без реального примера кода и того, что должно получиться, подсказать сложно.

                  Авторизация

                  через сервис Loginza:


                  Шаблоны MODX

                  1 2 Дальше »

                  Объектная
                  модель
                  MODX