Как записать опции товару?

Добрый день.

Нужно записать опции к товару, никак не пойму как это сделать. Опции типа combo-box, нужно записывать туда несколько значений. Пробовал много вариантов:

//Не понятно как сохранить
$product = $modx->getObject('msProduct', array(
  'id' => 555
));
$options = $product->getMany('Options');
foreach ($options as $option) {
	$option->set('', ''); // что тут писать?
	$option->save();
}

//Опция создается, но...
$option = $modx->newObject('msProductOption');
$option->set('key', 'vozrast');
$option->set('product_id', 555);
$option->set('value', '2222');
$option->save();

//.. как ее обновить потом?
$option = $modx->getObject('msProductOption', array(
	'key' => 'vozrast',
	'product_id' => 555
));
$option->set('value', '2222');
$option->save(); //не работает, ошибок нет
// или удалить
$option->remove(); //не работает, ошибок нет

//еще такой вариант, работает, но в опции с несколькими значениями отображает только последнее значение,
//и как записывать несколько значений не ясно
$product = $modx->getObject('msProduct', array(
	'id' => 555
));
$data = $product->getOne('Data');
$options = $data->get('options');
foreach ($options as $option) {
	print_r($option); //выводит только последнее значение опции
}
Андрей
06 сентября 2016, 10:37
modx.pro
6
7 702
0

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

Володя
06 сентября 2016, 14:13
2
0
можно было просто задействовать механизм создания/ обновления через процессоры…

вот так можно как вы хотели
// получаем продукт
$product = $modx->getObject('msProduct', array(
  'id' => 135
));

// получаем его опции
$options = $product->loadData()->get('options');

// добавляем какие то свои, например цвет
$options['color'][] = 'серобармалиновый';
$options['color'][] = 'серобармалиновый2';
$options['color'][] = 'синий';

// устанавливаем значения
foreach ($options as $k => $v) {
    if (is_array($v)) {
        $v = array_unique($v);
    }
    $product->set($k, $v);
}

// сохраняем изменения
$product->save();
    Андрей
    06 сентября 2016, 14:24
    0
    Да, в цвет он добавил, но у меня свои поля, которые я добавил в настройках Минишопа, например Тип, с ключом tip. Заменил color на tip — ничего не добавил.
      Володя
      11 сентября 2016, 12:58
      0
      попробуй вот так
      $rid = 135;
      	// массив с добавляемыми опциями
      	$values = array('color' => array('синий','белый');
      
      	/** @var $product msProduct */
              if (!$product = $modx->getObject('msProduct', $rid)) {
                  return $options;
              }
              $options = $product->loadData()->get('options');
      
              foreach ($values as $k => $v) {
                  if (!is_array($v)) {
                      $v = array($v);
                  }
                  if (isset($options[$k])) {
                      $options[$k] = array_merge($options[$k], $v);
                  }
                  else {
                      $options[$k] = $v;
                  }
              }
      
              foreach ($options as $k => $v) {
                  if (is_array($v)) {
                      $options[$k] = array_map('trim', $options[$k]);
                      $options[$k] = array_keys(array_flip($options[$k]));
                      $options[$k] = array_filter($options[$k]);
                  }
                  else {
                      $options[$k] = trim($options[$k]);
                  }
                  $product->set($k, $options[$k]);
              }
              $product->set('options', $options);
              $product->save();
        Кровельный
        25 июля 2023, 14:51
        1
        0
        Как из свойств товара-ресурса записать в одну опцию товара?
        Например если 2-3 значения, а 1 ключ, конечно можно использовать вариант в свойствах если там уже есть данные json, как многомерный массив, но мы сделаем тестовую опцию множественный выбор.
        1. Назовём опцию made_from
        2. Заведём в опцию значения (В настройках minishop2), чтобы получились значения:
          • Металла
          • Дерева

          • Вторсырья
          • Текстиля
          • Пластика

          * — не программно, вручную (если программно, то дописывайте код)
        3. Далее выполним:
          <?php
          $key = 'made_from'; // имя опции товара
          $resource = $modx->getObject('modResource', 44);
          $product = $modx->getObject('msProduct', $resource->id);
          //$arr = $resource->get('properties')['technicals']['Детали изготовлены из'];
          $arr = ['Пластика','Вторсырья'];
          $options = $product->loadData()->get('options');
          foreach ($arr as $k => $v) {
              $options[$key][$k] = $arr[$k];
          }
          $product->set('options', $options);
          $product->save();
        4. Готово. Теперь mFilter2 сможет фильтровать по опции. Если необходимо записать или обновить товары, то необходимо завернуть всё в getCollection
        nekto
        25 октября 2018, 16:52
        0
        А как через процессоры опции обновлять? Пробую так $response = $modx->runProcessor('resource/update', $params), не работает.
          Андрей
          25 октября 2018, 17:04
          0
          Вроде бы так
          $params['color'] = array('цвет 1', 'цвет 2');
          $params['option.ключ_своей_опции'] = array('параметр 1', 'параметр 2');

          Вообще можно распечатать массив продукта и посмотреть как там опции записаны
          $product = $modx->getObject('msProduct', $id);
          print_r($product->toArray());
        Виктор Долгий
        12 октября 2016, 13:49
        0
        Вот так делал это я:

        <?php
        $serviceOption = 'replaceTextInOption';
        
        $parentCategory = 641;
        $getOptionKey = 'flavor_volume';
        //$addText = 'Готовая база или основа';
        
        $replaceTextInOptionFind = ' мл';
        $replaceTextInOptionReplace = '';
        
        if (!$parents = $modx->runSnippet('pdoResources', array('returnIds' => 1, 'parents' => $parentCategory, 'where' => array('class_key' => 'msCategory'), 'limit' => 0))) {
        	$parents = $parentCategory;
        }
        // ! Добавить проверку, категория ли это товаров
        $parents = explode(",", $parents);
        
        foreach ($parents as $parent) {
        	$products = $modx->getCollection('msProduct', array('parent' => $parent));
        	foreach ($products as $product) {
        		if (!($product instanceof msProduct)) {
        			return "The resource with id = {$product->id} is not instance of msProduct.";
        		}
        		
        		if ($serviceOption == 'replaceTextInOption') {
        			if ($data = $product->getOne('Data')) {
        				$options = $data->get('options');
        			}
        			
        			foreach ($options as $optionKey => $optionValues) {
        				if ($optionKey == $getOptionKey) {
        					//echo print_r($options) . '
        ';
        					//echo print_r($optionValues) . '
        ';
        					//$options[$dataKey][0] = str_replace($replaceTextInOptionFind, $replaceTextInOptionReplace, $dataValue[0]);
        					
        					if (is_array($optionValues)) {
        						//return 777;
        						foreach ($optionValues as $arrayNumber => $optionValue) {
        							$options[$optionKey][$arrayNumber] = str_replace($replaceTextInOptionFind, $replaceTextInOptionReplace, $optionValue);
        						}
        						//sort($options[$optionKey]);
        						//$options[$optionKey] = $optionValues;
        						echo print_r($options) . '
        
        ';
        					}
        					$data->set('options', $options);
        					$data->save();
        					//return $dataKey;
        				}
        				//echo $dataKey;
        			}
        		}
        		
        		if ($serviceOption == 'replaceTextInField') {
        			//$product->set('weight', '0.01');
        			//$product->save();
        		}
        	}
        }
        Тут много мусора, но все же, думаю, разберешься. Ключевой момент — записать массив значений, в массиве опций, к нужной опции, а затем, сохранить весь массив опций.
          Дмитрий Храмов
          16 июня 2017, 00:39
          0
          $product = $modx->getObject('modResource', array('context_key' => 'web', 'id'=>'17'));
          $product->get('price_oct_day.value'); //получает значение опции price_oct_day
          $product->set('price_oct_day.value', 9); //А ВОТ ЭТА ШТУКА НЕ РАБОТАЕТ ХОТЬ УБЕЙ
          $product->save();
          Такая же проблема — не сетятся опции товара — тв сетятся, а опции почему то нет.
          Тестирую в консоли, надо продублировать опции другого контекста.
            Андрей
            16 июня 2017, 07:51
            2
            +1
            Там стандартные опции color, size задаются так
            $product->set('color', array('черный', 'белый'));

            А те опции которые создаешь сам так
            $options = array(
            	'option1' => array('value1', 'value2'),
            	'option2' => array('value1', 'value2')
            );
            
            $product->set('options', $options);
              Дмитрий Храмов
              25 июня 2017, 01:49
              1
              0
              Да, уже разобрался. Выложу свое решение, малоли поможет кому.
              Плагин дублирует опции товара из опций товара из другого контекста у которых совпадает alias. Используется minishop 2.4.11, начиная опции идут исключительно массивами.
              Вешается на OnDocFormSave
              <?php
              if ($modx->event->name=="OnDocFormSave" and $resource->get('class_key') == 'msProduct')
              {
                  $id = $resource->get('id');
                  $alias = $resource->get('alias');
                  $res = $modx->getObject('msProduct', $id);
                  
                  if ($res->get('context_key') != 'web'){
                  $options = $resource->loadData()->get('options');
                  $res2 = $modx->getObject('msProduct', array('context_key' => 'web', 'alias' => $alias));
                  
              // daily prices    
                  $tvv = $res->get('price_oct_day');
                  
                      if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_oct_day');
                          $options['price_oct_day'] = $tvv2;
                      }
                      
                  $tvv = $res->get('price_nov_day');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_nov_day');
                          $options['price_nov_day'] = $tvv2;
                      }
                  
                      $tvv = $res->get('price_dec_day');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_dec_day');
                          $options['price_dec_day'] = $tvv2;
                      }
                  
                          $tvv = $res->get('price_jan_day');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_jan_day');
                          $options['price_jan_day'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_feb_day');
                      if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_feb_day');
                          $options['price_feb_day'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_mar_day');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_mar_day');
                          $options['price_mar_day'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_apr_day');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_apr_day');
                          $options['price_apr_day'] = $tvv2;
                      }
              //monthly prices       
                      $tvv = $res->get('price_oct_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_oct_mon');
                          $options['price_oct_mon'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_nov_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_nov_mon');
                          $options['price_nov_mon'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_dec_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_dec_mon');
                          $options['price_dec_mon'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_jan_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_jan_mon');
                          $options['price_jan_mon'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_feb_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_feb_mon');
                          $options['price_feb_mon'] = $tvv2;
                      }
                      
                          $tvv = $res->get('price_mar_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_mar_mon');
                          $options['price_mar_mon'] = $tvv2;
                      }
                      
                      $tvv = $res->get('price_apr_mon');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('price_apr_mon');
                          $options['price_apr_mon'] = $tvv2;
                      }
              // other options
                      $tvv = $res->get('beach_dist');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('beach_dist');
                          $options['beach_dist'] = $tvv2;
                      }
                      $tvv = $res->get('bedrooms');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('bedrooms');
                          $options['bedrooms'] = $tvv2;
                      }
                      $tvv = $res->get('ac');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('ac');
                          $options['ac'] = $tvv2;
                      }
                      $tvv = $res->get('kitchen');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('kitchen');
                          $options['kitchen'] = $tvv2;
                      }
                      $tvv = $res->get('balcony');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('balcony');
                          $options['balcony'] = $tvv2;
                      }
                      $tvv = $res->get('room_type');
                          if ( empty($tvv) )
                      {
                          $tvv2 = $res2->get('room_type');
                          $options['room_type'] = $tvv2;
                      }
              
              
                  $res->set('options', $options);
                  $res->save();
                  }
                  
              }
                Андрей
                25 июня 2017, 07:32
                +1
                Думаю можно проще сделать, получить все заведенные в админке опции и в цикле пройтись по всем

                $all_options = $modx->getCollection('msOption');
                
                foreach($all_options as $opt) {
                	$key = $opt->get('key');
                
                	if ( empty($res->get($key)) ) {
                		$options[$key] = $res2->get($key);
                        }
                }
            perfkirill
            14 ноября 2018, 09:47
            1
            0
            Добрый день,

            Помогите, пожалуйста.

            Я распарсиваю артикул и помещаю нужные данные в нужные поля.

            С цветом и размером проблем нет.
            Но есть проблемы с свойствами товара (Опции minishop2)

            Вот код
            <?php
            
                    $article = $resource->get('article');
                    
                   
                    //Поиск цвета
                    preg_match('/[A-z]{2,}/',$article,$color);
                   
                    //Поиск размера
                    preg_match('/\d{2}$/',$article,$size);
                     $size = "[".$size[0]."]";
                    //Поиск материала
                    preg_match('/0\d{2}/',$article,$material); 
                    //Поиск модели
                    $model_article = substr($article,8,5);
                    preg_match('/0\d{2}?-?\d/',$model_article,$model); 
            
                    
                   
                    $resource->set('size', $size);
                
                    $color_arr_json = json_encode($color);
                    $resource->set('color', $color_arr_json);
                    
                    
                    // Работа с опциями
                   $id = $resource->get('id');
                   
                   $product = $modx->getObject('msProduct', $id);
                   //пробовал так
                  // $options['cloth'] = "123";
                   
                   //пробовал так
                   $options = array(
                    
                    	'composition' => array('value1', 'value2')
                    );
            
                    $product->set('options', $options);
                    $product->save();
            В итоге пустота.
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              12