programming languages

Spreadsheet_Excel_Writer генерит пустой файл

В общем была проблема после переезда на другой хостинг, на timeweb. Попросил поставить Spreadsheet_Excel_Writer, ТП быстро отреагировала и поставила библиотеку, но она напроч отказывалась писать в файл. Т.е. файл генерила, но данные не записывались в файл. Я не дождался ответа в выходной день, оказывается у них админы в выходные не работают, поставил другую библиотеку для работы с Exel, PHPExcel называется. В работе даже полегче чем выше указанная. Она потребовала настройки mbstring.func_overload != 2, что и было сделано, оказалось что и Spreadsheet_Excel_Writer не работала по той же причине, в общем проблема тут mbstring.func_overload

Выводим в header.php компонент с параметрами переданными в теле странцы

Итак чтобы не забывать и постоянно не вспоминать как это делается запишу.
Нам нужно в хидере вывести какую либо информацию, но не просто вставить компонент в шаблон, а передавать в этот компонент какие-то параметры которые мы получаем только в теле страницы.

Делается это так. Пишется функция вида

function componentHeader($text)
{
	global $APPLICATION;
	$arParams = $APPLICATION->GetPageProperty('PARAMS');
	if(is_array($arParams))
	{
		ob_start();
			$APPLICATION->IncludeComponent('demo:test', '', $arParams);
			$contentTime = ob_get_contents();
		ob_end_clean();
		return $contentTime;
	}
}

кладем ее как через init.php и в хидере выводим $APPLICATION->AddBufferContent(«componentHeader»); должно работать.

Мини GetList для файлов

В исходниках битрикса есть CAllFile::GetList($arOrder, $arFilter, $arParams); но он видимо служит для внутреннего использования и не описан в документации. Нам нужно выбрать описание по 10 файлам за раз, этот метод, в качестве параметра фильтра массив из ID файлов не принял. Пришлось накидать свою функцию.

function __arfileGetList($ar_FileID)
{
	if(is_array($ar_FileID) && count($ar_FileID) > 0)
	{
		global $DB;
		$rs_File = $DB->Query(
			"SELECT * FROM b_file WHERE ID IN 
                               (". implode(',', $ar_FileID). ")",
			false,
			"FILE: ".__FILE__." LINE: ".__LINE__
		);
		while($ar_File = $rs_File->Fetch())
		{
			$ar_Result[] = $ar_File;
		}

		if(is_array($ar_Result) && count($ar_Result) > 0)
			return $ar_Result;
	}
}

P/S
Не забудте проверить $ar_FileID, чтобы там были именно ID файлов…

Битрикс и большой кэш по ID

Итак представим что у вас или у вашего клиента большой, высоко-посещаемый сайт. Также представим инфоблок в котором больше 80k элементов. Наверняка у этих элементов есть детальное описание  и я уверен 99,9% что ID кэша это ID вашего элемента.

Итак у нас получается что в папке допустим /bitrix/cache/object_80k/ — 80 000 папок с кэшем, т.е.

/bitrix/catche/object_80k/1

/bitrix/catche/object_80k/2

/bitrix/catche/object_80k/3

/bitrix/catche/object_80k/n

/bitrix/catche/object_80k/80 000

Какой бы у вас не был сервер, поиск папки в общем списке из 80k занимает время. Плюс если сайт посещаемый то вы догадываетесь что происходит, нагрузка на ровном месте, даже я бы сказал в том месте где мы пытаемся ее уменьшить.

Итак решение, на мой взгляд просто очень красивое и элегантное, его подсказал мой коллега  Николай Рыжонин.

function __getGenerationCachePath($id)
{
    $hash = md5($id);
    $path = substr($hash,-4,2).'/'.substr($hash,-2);
    return $path;
}

Пример:

$ob_Cache     = new CPHPCache;
$i_CacheTime  = 3600;
$s_CacheID    = $ID;
$s_CachePatch = "/object_80k/" . __getGenerationCachePath($ID) . "/" . $ID . "/";
if($ob_Cache->InitCache($i_CacheTime, $s_CacheID, $s_CachePatch))
{
    $ar_Cache  = $ob_Cache->GetVars();
    $ar_Result = $ar_Cache['ITEAM'];
}
else
{
    $ar = ''; // выборка
    if($obCityCache->StartDataCache())
    {
        $obCityCache->EndDataCache(array('ITEAM' => $ar));
    }
}

Итак функция создаст путь вида /object_80k/as/df/ID и тем самым разобьет 80k папок на под папки, тем самым уменьшит время поиска кэша и общую нагрузку на сервер.

Да и еще важный момент, функция написана с учетом что ID > 100 000k. хотя тем кому это пригодится это не важно…

str_replace, если работаем с массивами

Сегодня заметил небольшую особенность в стандартной php функции, которую раньше как-то не замечал. Вылез баг в замене значения по маске через  str_replace. Код выглядит вот так :

    $ar_ResultList[] = str_replace(
	array("#ID#", "", "", "", "#CODE#", 
"#CITY_CODE#", "#DETAIL_URL#", "#HOTEL_CODE#"),
	$ar_ObjectFiled,
	$s_LinkTemplates
   );

Это уже исправленный код, т.е если мы ищем и заменяем в массиве то ключи должны совпадать и по расположению, т.е. по ключам.

Класс для сортировки массива, usort [php]

Пример реализации выборки из нескольких инфоблоков с постраничной навигацией и сортировкой.

Задача:

1) Выбрать список элементов из нескольких инфоблоков в таблицу;

2) Иметь возможность сортировки элементов;

3) Должна работать постраничная навигация

Итак этот пример можно использовать при небольшом кол-ве выбираемых элементов, думаю максимум до 100, естественно с кэшированием.

Первым делом нужно выбрать все данные в ассоциативный массив, например вот такой:

 [ITEAM] => Array
        (
            [0] => Array
                (
                    [CITY_NAME] => value
                    [CITY_DETAIL_URL] => value
                    [OBJECT_NAME] => value
                    [OBJECT_ID] => 2487
                    [DATE_CREATE] => 02.07.2006
                    [STATUS] => Y
                    [PAID_STATUS] => Y
                    [DATEIL_OBJECT_URL] => value
                )

            [1] => Array
                (
                    [CITY_NAME] => value
                    [CITY_DETAIL_URL] => value
                    [OBJECT_NAME] => value
                    [OBJECT_ID] => 2489
                    [DATE_CREATE] => 02.07.2006
                    [STATUS] => Y
                    [PAID_STATUS] => N
                    [DATEIL_OBJECT_URL] => value
                )

Continue reading

Ajax и IE7: Ошибка c00ce56e и как ее исправить, в Bitrix не исключение…

Ошибка эта возникает, когда сервер передает IE неизвестную кодировку. То есть, возможна ситуация, когда на одном сервере ваш скрипт будет работать нормально, а на другом —  возникнет подобная ошибка.

То есть, передается, как правило — «utf8» а по стандарту должно «utf-8«. То есть, на этот раз Internet Explorer ведет себя вполне корректно (хотя, мог бы и простить, как делает FireFox, например), а гнилые помидоры — тому, кто настраивал web-сервер.

Как исправить? Варианта два:

  1. Поправить настройки Apache
  2. B самом начале серверного скрипта Ajax принудительно указать кодировку: header(‘Content-type: text/html; charset=utf-8’);

Поскольку, мы можем не знать настроек сервера, где будет работать наш скрипт, указание данного заголовка header(‘Content-type: text/html; charset=utf-8’);, я считаю, обязательно.

В битриксе это ошибка возникает допустим при обращение аяксом к компоненте в которой подключается js, без js все работает. Так что или выносим js из компонента или пользуемся советами выше.

решение нашли тут

Инфоблоки +, события [bitrix api]

Хочу предостеречь от очень каверзной особенности работы с расширенными инфоблоками у Битрикса, так называемыми Инфоблоками +.

Если вы используете обработчик на редактирование элемента OnBeforeIBlockElementUpdate, и изменяете в нем хоть одно свойство, то вам нужно указать в массиве параметров все свойства этого элемента. Иначе  они будут затерты.

Это происходит только на инфоблоках + и не с включенным документооборотом для этого инфоблока. Все дело в массиве PROPERTY_VALUES, в котором вы меняете значение какого-то свойства. Подвох в том что вы не используете метод $el->Update($ID, $arParams) в самом обработчике, и это ошибка трудно уловима, по сути обработчик переопределяет   $arParams[‘PROPERTY_VALUES’], по этому в нем будет только ваше изменение из обработчика. В этом случае, если вы будете использовать $el->Update($ID, $arParams) к этому инфоблоку в другом месте, свойства будут сбрасываться.

События хорошая штука, но нужно внимательнее сними работать, ими не стоит злоупотреблять.

Битрикс AJAX [bitrix-ajax-api]

Почему-то многие не охотно используют битриксовую библиотеку аякса, почти всегда делая предпочтения в сторону Jquery или других js библиотек. Не сомненно что Jquery очень не плохая библиотека и отлично работает с ajax, но чтобы свободно разрабатывать сайты не 1с-Битрикс надо знать родное API.

Пост для новичков, думаю будет полезно. Рассматриваем только ajax-овую часть библиотеки, ее основу.

Continue reading