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

Дополнение: minishop2

Добрый день.

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

Комментарии (8)

  1. Володя 06 сентября 2016, 14:13 # 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();
    
    
    
    1. Андрей 06 сентября 2016, 14:24 # 0
      Да, в цвет он добавил, но у меня свои поля, которые я добавил в настройках Минишопа, например Тип, с ключом tip. Заменил color на tip — ничего не добавил.
      1. Володя 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();
        
        
    2. Виктор Долгий 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();
      		}
      	}
      }
      Тут много мусора, но все же, думаю, разберешься. Ключевой момент — записать массив значений, в массиве опций, к нужной опции, а затем, сохранить весь массив опций.
      1. Дмитрий Храмов 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();
        Такая же проблема — не сетятся опции товара — тв сетятся, а опции почему то нет.
        Тестирую в консоли, надо продублировать опции другого контекста.
        1. Андрей 16 июня 2017, 07:51 # +1
          Там стандартные опции color, size задаются так
          $product->set('color', array('черный', 'белый'));
          

          А те опции которые создаешь сам так
          $options = array(
          	'option1' => array('value1', 'value2'),
          	'option2' => array('value1', 'value2')
          );
          
          $product->set('options', $options);
          
          1. Дмитрий Храмов 25 июня 2017, 01:49 # 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();
                }
                
            }
            
            1. Андрей 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);
                      }
              }
              
              
        Вы должны авторизоваться, чтобы оставлять комментарии.