Подскажите, столкнулись с такой проблемой записи значений у свойств типа 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).", ".