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

Добрый день.

Нужно записать опции к товару, никак не пойму как это сделать. Опции типа 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
2
1 607
0

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

Володя
06 сентября 2016, 14:13
1
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();
Виктор Долгий
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
    1
    +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);
                }
        }