Задать вопрос
yous
@yous

Bitrix изменение свойства CIBlockElement::SetPropertyValuesEx?

Подскажите, столкнулись с такой проблемой записи значений у свойств типа STRING, но возможно и у LIST такая же проблема, вообще эта проблема касается именно значений который STRING

Вся проблема сводится к тому, что в методе CIBlockElement::SetPropertyValuesEx задается массив ["CODE"=>"Значение"] для добавления, изменения значения свойства и управлять другими полями типа VALUE_ENUM, VALUE_NUM нет возможности из этого метода, пробовали вот так ["CODE"=["VALUE"=>Значение, "VALUE_ENUM"=>0, "VALUE_NUM"=>0]] не воспринимает, ну и понятно потому что в методе CIBlockElement::SetPropertyValuesEx можно определить в $PROPERTY_VALUES только VALUE и DESCRIPTION, а VALUE_ENUM, VALUE_NUM берутся из VALUE

и вот собственно в чем проблема, все значения из VALUE приводятся к intval() а если глянуть, что собственно делает intval() в доки php то увидим это

intval ( mixed $value , int $base = 10 ) : int

// Замечание:
// Если base равно 0, основание системы счисления определяется форматом value:
// если строка включает префикс "0x" (или "0X"), основание выбирается равным 16 (шестнадцатеричным);
// иначе, если строка начинается с "0", основание равно 8 (восьмеричное);
// иначе, основание выбирается равным 10 (десятеричным).


Вот и получаем ошибку в запись базы, если мы передаём строку начинающуюся с числа и заканчивающуюся символом.
например мы хотим записать значение свойства Артикул со значением 20008404080S, что сделает CIBlockElement::SetPropertyValuesEx
в VALUE он запишет строку 20008404080S
в VALUE_ENUM он запишет число приведенное из строки 20008404080S => 20008404080
между делом, поле в базе VALUE_ENUM имеет 10 символов, а мы пытаемся записать 11 на что справедливо получаем ошибку Out of range

а вот что у нас происходит в самом методе SetPropertyValuesEx

$maxValuesLen = $DB->type=="MYSQL"?1024:0;
            $strSqlValues = "";
            foreach($properties as $property_id=>$values)
            {
                foreach($values as $value)
                {
                    if($value["VALUE"] <> '')
                    {
                        $strSqlValues .= ",\n(".
                            $property_id.", ".
                            $ELEMENT_ID.", ".
                            "'".$DB->ForSQL($value["VALUE"])."', ".
                            intval($value["VALUE"]).", ".
                            CIBlock::roundDB($value["VALUE"]).", ".
                            ($value["DESCRIPTION"] <> ''? "'".$DB->ForSQL($value["DESCRIPTION"])."'" : "null")." ".
                        ")";
                    }
                    if(mb_strlen($strSqlValues) > $maxValuesLen)
                    {
                        $DB->Query($strSqlPrefix.mb_substr($strSqlValues, 2));
                        $strSqlValues = "";
                    }
                }
            }


как видим VALUE_ENUM и VALUE_NUM

"'".$DB->ForSQL($value["VALUE"])."', ".
                            intval($value["VALUE"]).", ".
                            CIBlock::roundDB($value["VALUE"]).", ".

записываются без проверки на совпадение VALUE

Так вот вопрос, как добавить значение свойства типа STRING и записать в VALUE_ENUM=> NULL и VALUE_NUM=>0 ?

UPD1. Решение выбрал такое, наследуемся от класса CIBlockElement и меняем метод SetPropertyValuesEx на нужный нам код

class CIBlockElementModify extends CIBlockElement
{
	public static function SetPropertyValuesEx($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $FLAGS=array())
	{

...

$maxValuesLen = $DB->type=="MYSQL"?1024:0;
			$strSqlValues = "";
			foreach($properties as $property_id=>$values)
			{
				foreach($values as $value)
				{
					if($value["VALUE"] <> '')
					{
						$strSqlValues .= ",\n(".
							$property_id.", ".
							$ELEMENT_ID.", ".
							"'".$DB->ForSQL($value["VALUE"])."', ".
							(intval($value["VALUE"])===$value["VALUE"]?intval($value["VALUE"]):'null').", ".
							(intval($value["VALUE"])===$value["VALUE"]?CIBlock::roundDB($value["VALUE"]):0).", ".
							($value["DESCRIPTION"] <> ''? "'".$DB->ForSQL($value["DESCRIPTION"])."'" : "null")." ".
						")";
					}


меняем вот на это, если при intval значения совпадают по типу, то пишем как и было, если нет ставим null и 0 для VALUE_ENUM и VALUE_NUM

(intval($value["VALUE"])===$value["VALUE"]?intval($value["VALUE"]):'null').", ".
(intval($value["VALUE"])===$value["VALUE"]?CIBlock::roundDB($value["VALUE"]):0).", ".
  • Вопрос задан
  • 1114 просмотров
Подписаться 1 Простой 7 комментариев
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы