Воеводский Михаил

Воеводский Михаил

Был в сети 30 марта 2026, 14:44
Заказы не принимаю
/* Меняю значение опции на полученное */
            $o = $modx->newObject('msProductOption', array(
                'product_id' => $r->id,
                'key' => 'options_length',
                'value' => trim($_POST['options_length'])
            ));
            $o->save();
Не надо так делать. Достаточно проверить существование опции у товара, а выставлять значение опции самому товару. Как минимум, такой механизм я понял из чтения исходников MS 2.2 (с опциями мне еще не приходилось работать).

<?php
$optionKey = 'options_length';
$optionKeys = $r->getOptionKeys();
if (!in_array($optionKey, $optionKeys) and $option = $modx->getObject('msOption', array('key' => $optionKey))) {
    $productOption = $modx->newObject('msProductOption');
    $productOption->addOne($option, 'Option');
    $productOption->addOne($r, 'Product');
}
$r->set($optionKey, trim($_POST[$optionKey]));
$r->save();
Связь просто надо было сохранить
$linkProducts->save();
Не обратил внимание, что у товара нет прямой связи (на уровне xPDO) со связью msLink.
Потому все равно достаточно одного сохранения, но с другой стороны — сохранить $linkProducts, а все остальные объекты тоже сохранятся. То есть,
$n->save()
совершенно необязательное действие, если есть строка выше.
Я не совсем понимаю, именно создаем, а не получаем
Я не совсем понял Вашу идею, потому в коде создал связь. Конечно, можно использовать созданную ранее.

$link = $modx->newObject('msLink', 1);
Бесполезная запись, тк newObject() вторым параметром принимает массив. Если передано что угодно другое, параметр игнорируется.

Более того, даже если передать массив
array('id' => 1);
, то все равно новому объекту не будет установлено значение поля id == 1. Причина: метод fromArray(), который используется для установки переданных значений созданному объекту, по умолчанию не выставляет значение первичного ключа, коим является поле id.

После создания объекта требуется либо явно задать первичный ключ через set():
$link->set('id', 1);
, либо указать третий параметр для fromArray():
$link->fromArray(array('id' => 1), '', true);
Если же требуется получить созданную ранее связь по ее id, используйте такой вариант:
$link = $modx->getObject('msLink', $id);
Код написал без проверки. В теории должен работать.

<?php

/* Получаем товар, который надо копировать */
if ($r = $modx->getObject('msProduct', (int)$_GET['rid'])) {

    /* Если товар создается с такими же свойствами, корректнее их брать полностью */
    $productData = $r->toArray();
    /* Сбрасываем некоторые свойства оригинального товара */
    unset($productData['publishedon'], $productData['publishedby']);
    /* Устанавливаем правильные свойства */
    $productData['createdon'] = time();
    $productData['createdby'] = $modx->user->id;
    /* Создаем и сохраняем */
    $n = $modx->newObject('msProduct', $productData);

    /* Создаем новую связь */
    $link = $modx->newObject('msLink', array(
        'type' => 'one_to_many',
        'name' => 'Название связи',
    ));
    
    /* Создаем новую связку */
    $linkProducts = $modx->newObject('msProductLink');
    /* Добавляем товары в связку */
    $linkProducts->addOne($r, 'Master');
    $linkProducts->addOne($n, 'Slave');
    /* Добавляем основную связь в связку */
    $linkProducts->addOne($link, 'Link');

    /* Создаем новую опцию */
    $option = $modx->newObject('msProductOption', array('key' => $r->get('options_phone')));
    /* Добавляем опцию к новому товару */
    $n->addOne($option, 'Options');

    /* Сохраняем товар. Благодаря связыванию объектов через addOne(), все необходимые ID подставляются автоматически */
    $n->save();
    
}
Ради интереса только что проверил:
<?php
$a = null;
$b = false;
if ((!$a) === (!$b)) echo 'equal';
else echo 'not equal';
// equal
Вывод прост:
!$modx->getObject()
даст тот же результат, что и
is_null($modx->getObject())
, но первый вариант воспринимается проще и быстрее при чтении кода.