При создании магазина часто приходится делать ajax корзину, то что есть в стандарте меня не совсем устраивает, поэтому мы делаем свою простую гибкую корзину, с возможностью удалять товары и изменять их количество Первым делом нам надо будет загрузуть jquery , грузить мы будем его с хранилища гугла .
Теперь нам надо написать скрипт который будет передавать и забирать данные о состоянии корзины с помощью ajax, удаление товаров которые уже в корзине, изменение количества товаров.
<script type="text/javascript">
/* Function for ours ajax inquiry */
function ajaxpostshow(urlres, datares, wherecontent ){
$.ajax({
type: "POST",
url: urlres,
data: datares,
dataType: "html",
success: function(fillter){
$(wherecontent).html(fillter);
}
});
}
$('.input-basket-submit').live("click",function(){
var addbasketid = $(this).attr('id');
ajaxpostshow("/include/ajax/basket.php", addbasketid, ".basket" );
return false;
});
/* Inquiry ajax at removal of the goods from a basket */
$('.basket .basket-list-delete').live("click",function(){
var deletebasketid = $(this).attr('id');
ajaxpostshow("/include/ajax/basket.php", deletebasketid, ".basket" );
return false;
});
/* Inquiry ajax at change of quantity of the goods */
$(".basket .basket-count-update").live("change", function(){
var countbasketid = $(this).attr('id');
var countbasketcount = $(this).val();
var ajaxcount = countbasketid + '&ajaxbasketcount=' + countbasketcount;
ajaxpostshow("/include/ajax/basket.php", ajaxcount, ".basket" );
return false;
});
</script>
Далее создадим файл который будет принимать и обрабатывать данные приходящие в корзину назовем его basket.php , разместим его в папке /include/. В нем у нас находится три обработчика ajax: добавление в корзину, изменение количества и удаление товара из корзины.
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
?>
<?
CModule::IncludeModule("sale");
CModule::IncludeModule("catalog");
/* Addition of the goods in a basket at addition in a basket */
if($_POST["ajaxaddid"] && $_POST["ajaxaction"] == 'add'){
Add2BasketByProductID($_POST["ajaxaddid"], 1, array());
}
/* Goods removal at pressing on to remove in a small basket */
if($_POST["ajaxdeleteid"] && $_POST["ajaxaction"] == 'delete'){
CSaleBasket::Delete($_POST["ajaxdeleteid"]);
}
/* Changes of quantity of the goods after receipt of inquiry from a small basket */
if($_POST["ajaxbasketcountid"] && $_POST["ajaxbasketcount"] && $_POST["ajaxaction"] == 'update'){
$arFields = array(
"QUANTITY" => $_POST["ajaxbasketcount"]
);
CSaleBasket::Update($_POST["ajaxbasketcountid"], $arFields);
}
?>
<?$APPLICATION->IncludeComponent(
"bitrix:sale.basket.basket.small",
"smallbasker",
Array(
"PATH_TO_BASKET" => "/personal/cart/",
"PATH_TO_ORDER" => "/personal/order/"
)
);?>
В конце мы вызываем компонент , в нем можем стилизовать вывод корзины, так же в коде у меня присутствует вызов шаблона компонента вот код самого шаблона вы его естественно украсите под свои нужды
В шаблоне компонента корзины мы создали ссылку на удаление товара из корзины и изменение количества товаров. Так же еще необходимо создать в шаблоне страницы место для вывода корзины .
Доброго всем дня. Продолжаю делиться своими наработками...
Итак, у меня есть задача: Для БУС под редакцией "Старт" необходимо выводить в инфоблоке в зависимости от страны пользователя разные поля.
Для этого воспользовался модулем:
Для этого выкачиваем вот файлы:
Readme - чтоб почитать, как же оно все работает;
geoip.inc - файл с основным набором функций для работы модуля
GeoIP.dat - база данных IP адресов (Обновляется не на столько часто, чтобы переживать, что когда-нибудь наш скрипт не сможет определить страну пользователя... А раз в год этот файлик можно и заменить....)
Закидываем 2 последних файла в корень сайта и тут же создаем тестовый файлик (geo.php) который нам покажет, что механизм определения страны все-таки работает...
Содержимое файла приблизительно такое:
<?
include("geoip.inc");
function getRealIpAddr() // Функция, определяющая реальный ИП пользователя
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
$realip=getRealIpAddr();
$gi = geoip_open("GeoIP.dat",GEOIP_STANDARD);
echo $value=geoip_country_code_by_addr($gi,getRealIpAddr()); покажет код страны пользователя
geoip_close($gi);?>
С непосредственным определением страны закончили.
Теперь нужно это применить к разработке.
Для этого, в php_interface/init.php создаем обработчик события :
<?
// файл /bitrix/php_interface/init.php
function GetUserCountry()
{
global $USER;
$USER->SetParam("UserCountry", "UA"); //работает только для авторизованных
}
AddEventHandler("main", "OnBeforeProlog", "GetUserCountry", 50);
?>
Таким образом, получаем параметр пользователя, со значением кода страны, который в последствии сможем использовать на сайте.
Теперь нужно перенести определение страны пользователя из тестового файла "geo.php" в init.php.
подключаем файлик с функциями:
include($_SERVER["DOCUMENT_ROOT"]."/geoip.inc");
переносим функцию реального ИП пользователя (не знаю на сколько она 100%-но рабочая - нашел ее на одном из форумов. Думаю профессиональные пользователи ее все-таки обойдут, но сайт на таких не рассчитан, так что вполне пойдет):
function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
добавляем определение кода страны в функцию обработчика. Код страны запишем в сесиию:
$_SESSION['UserCountry']=$value;
В результате файл init.php будет иметь вид:
<?
// файл /bitrix/php_interface/init.php
include($_SERVER["DOCUMENT_ROOT"]."/geoip.inc");
function GetUserCountry()
{
$realip=getRealIpAddr();
$IPDBPATH=$_SERVER['DOCUMENT_ROOT'].'/GeoIP.dat'; //задаем путь к базе
$gi = geoip_open($IPDBPATH,GEOIP_STANDARD); //получаем данные из базы
$value=geoip_country_code_by_addr($gi,getRealIpAddr()); //получаем данные для ИП пользователя
geoip_close($gi); //закрываем файл с базой
global $USER;
$USER->SetParam("UserCountry", $value);
$_SESSION['UserCountry']=$value;
}
function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
AddEventHandler("main", "OnBeforeProlog", "GetUserCountry", 50);
?>
В итоге, для любого авторизованного пользователя в свойстве "UserCountry" будет код его страны. А для всех остальных - данные берем из сессии (в принципе хватит и сесии, но оставлю, вдруг кому пригодится использовать разные данные для авторизованных и для гостей...)
Дальше в коде, в шаблонах компонентов или на страницах, где нужно получать данное значение вставляем нечто похожее на:
<? global $USER; if ($USER->IsAuthorized()){ $COUNTRYCODE=$USER->GetParam("UserCountry"; } else { $COUNTRYCODE=$_SESSION["SESS_AUTH"]["UserCountry"]; } ?>
в итоге в переменной $COUNTRYCODE будет код страны посетителя сайта...
Вот такой вот механизм получился. Я на 100% уверен, что все это можно еще оптимизировать. Может быть в следующий раз этим и займусь...
Доброго всем дня. Продолжаю делиться своими наработками...
Итак, у меня есть задача: Для БУС под редакцией "Старт" необходимо выводить в инфоблоке в зависимости от страны пользователя разные поля.
Для этого воспользовался модулем:
Для этого выкачиваем вот файлы:
Readme - чтоб почитать, как же оно все работает;
geoip.inc - файл с основным набором функций для работы модуля
GeoIP.dat - база данных IP адресов (Обновляется не на столько часто, чтобы переживать, что когда-нибудь наш скрипт не сможет определить страну пользователя... А раз в год этот файлик можно и заменить....)
Закидываем 2 последних файла в корень сайта и тут же создаем тестовый файлик (geo.php) который нам покажет, что механизм определения страны все-таки работает...
Содержимое файла приблизительно такое:
<?
include("geoip.inc");
function getRealIpAddr() // Функция, определяющая реальный ИП пользователя
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
$realip=getRealIpAddr();
$gi = geoip_open("GeoIP.dat",GEOIP_STANDARD);
echo $value=geoip_country_code_by_addr($gi,getRealIpAddr()); покажет код страны пользователя
geoip_close($gi);?>
С непосредственным определением страны закончили.
Теперь нужно это применить к разработке.
Для этого, в php_interface/init.php создаем обработчик события :
<?
// файл /bitrix/php_interface/init.php
function GetUserCountry()
{
global $USER;
$USER->SetParam("UserCountry", "UA"); //работает только для авторизованных
}
AddEventHandler("main", "OnBeforeProlog", "GetUserCountry", 50);
?>
Таким образом, получаем параметр пользователя, со значением кода страны, который в последствии сможем использовать на сайте.
Теперь нужно перенести определение страны пользователя из тестового файла "geo.php" в init.php.
подключаем файлик с функциями:
include($_SERVER["DOCUMENT_ROOT"]."/geoip.inc");
переносим функцию реального ИП пользователя (не знаю на сколько она 100%-но рабочая - нашел ее на одном из форумов. Думаю профессиональные пользователи ее все-таки обойдут, но сайт на таких не рассчитан, так что вполне пойдет):
function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
добавляем определение кода страны в функцию обработчика. Код страны запишем в сесиию:
$_SESSION['UserCountry']=$value;
В результате файл init.php будет иметь вид:
<?
// файл /bitrix/php_interface/init.php
include($_SERVER["DOCUMENT_ROOT"]."/geoip.inc");
function GetUserCountry()
{
$realip=getRealIpAddr();
$IPDBPATH=$_SERVER['DOCUMENT_ROOT'].'/GeoIP.dat'; //задаем путь к базе
$gi = geoip_open($IPDBPATH,GEOIP_STANDARD); //получаем данные из базы
$value=geoip_country_code_by_addr($gi,getRealIpAddr()); //получаем данные для ИП пользователя
geoip_close($gi); //закрываем файл с базой
global $USER;
$USER->SetParam("UserCountry", $value);
$_SESSION['UserCountry']=$value;
}
function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
AddEventHandler("main", "OnBeforeProlog", "GetUserCountry", 50);
?>
В итоге, для любого авторизованного пользователя в свойстве "UserCountry" будет код его страны. А для всех остальных - данные берем из сессии (в принципе хватит и сесии, но оставлю, вдруг кому пригодится использовать разные данные для авторизованных и для гостей...)
Дальше в коде, в шаблонах компонентов или на страницах, где нужно получать данное значение вставляем нечто похожее на:
<?
global $USER;
if ($USER->IsAuthorized()){
$COUNTRYCODE=$USER->GetParam("UserCountry";
} else {
$COUNTRYCODE=$_SESSION["SESS_AUTH"]["UserCountry"];
}
?>
В итоге в переменной $COUNTRYCODE будет код страны посетителя сайта... Тестовый файлик определения страны (geo.php) в принципе можно уже и удалить....
Вот такой вот механизм получился. Я на 100% уверен, что все это можно еще оптимизировать. Может быть в следующий раз этим и займусь...
В интернете легко можно найти много статей на тему клиентской оптимизации, и ещё больше сайтов, разработчики которых уделили мало внимания этой теме. Хотя это отличный способ ускорить загрузку страниц своего сайта. Из основных рекомендаций выделим следующие:
Уменьшение количества запросов (особенно тех которые указаны в head страницы)
Использование gzip
Это, конечно, не всё, но именно эти рекомендации легче всего реализовать, и они принесут наиболее ощутимый эффект.
Для анализа откроем на CMS Bitrix. Я взял 10 сайтов с 1-й страницы и с помощью Firebug оценил их оптимизированность (главные страницы) по следующим параметрам:
Общее число запросов, число запросов css-файлов, число запросов js-файлов.
Использование сжатия там, где это возможно.
И что же выяснилось? Запросы:
Из 10 сайтов только 3 имели число css-файлов меньше 5-ти Из 10 сайтов только 3 имели число js-файлов меньше 5-ти Остальные имели количество css-файлов от 7 до 19-ти, количество js-файлов от 6 до 55-ти (!) и большинство этих файлов подключались в <head> страницы, то есть блокировали отображение страницы до завершения загрузки.
Сжатие
Только 4 сайта применяют gzip-сжатие при отдаче html, css, js.
Итак, вроде бы основы, однако, разработчики часто при них забывают.
Казалось бы, причём здесь Bitrix? Но у него есть одна особенность - страницы часто формируются из компонентов, каждый из них подключает файл style.css. Это удобно - включил компонент, стили подключились, отключил - они не грузятся. Обычный сайт содержит несколько компонентов на странице - каждый добавляет свои стили. Однако состав этих компонентов меняется редко, и в этом случае файлы целесообразно объединять. Именно этим пренебрегли 7 из 10 сайтов и подключали много css-файлов размерами 500-600 байт, а это не позволяет эффективно использовать соединение с сервером
Подведём итоги. Для ускорения сайта "лёгким" путём достаточно сделать следующее:
Если состав компонентов на странице постоянный, их стили нужно объединить в 1 файл. Для главной можно сделать следующее - все стили компонентов, которые есть на главной и других страницах, переносим в главный файл стилей template_styles.css. Стили компонентов, которые включены только на главной, объединяем в 1 файл. Итого на главной странице будут подключены всего 2 css-файла.
Обязательно договориться с хостерами о включении gzip-сжатия. Nginx обычно собирается с модулями, реализующими это и включить сжатие - дело быстрое и беспроблемное.
Решить эти 2 вопроса можно за несколько часов, однако польза будет большой и увеличение скорости загрузки может стать заметным даже на глаз!
Мы решили не отставать от других и выпустить под собственным брендом решение в маркетплэйс. Будет ли интересен некий "дневник", в котором рассказывается об этапах разработки решения и о нюансах этой разработки (в первую очередь с точки зрения менеджера)? Видимо, решение приму по рейтингу сообщения.
И второй вопрос: если интересно - то о чем именно вы бы хотели прочитать?
На днях пришлось сопоставить контакты и компании в CRM Bitrix (Корпоративный Портал - Бизнес Процессы).Импортировали из CSV компании и контакты, сопоставили одним не столь сложным SQL запросом
update b_crm_contact AS a
LEFT JOIN b_crm_company AS b
ON a.comments = b.title
set a.company_id= b.id
Ни при каких обстоятельствах не давайте добраться встроенному поисковику битрикса до php-фреймворков, которые вы могли использовать на сайте. Индексация в таком случае может не закончится никогда.
Метакомпоненты Уже неоднократно было «брожение мыслей» относительно неких универсальных компонент. Их не выставляли в качестве серебряной пули решающей все задачи, а позиционировали как хорошее подспорье разработчику. Если вынужден собирать функционал типовой или не очень. И стоит перед выбором: кастомизировать стандартные компоненты или писать свои. Сейчас я буду высказываться со своей колокольни, поэтому если моя тока зрения кажется неверной, то добро пожаловать в комментарии.
Что они из себя представляют и зачем нужны В 80% случаев работа ведётся с инфоблоками. Т.е. это различные выборки данных и их показ. Довольно часто делают на стандартных компонентах news.* и при необходимости их модифицируют с выносом в своё пространство имён или пишутся result_modifer ы для работы с недостающими данными. На нескольких проектах, где было понятно, что связей между инфоблоками будет много и придётся основательно кастомизировать типовые компоненты было принято решение написать 3 абстрактных компонента: форма фильтрации, список, детальная. Это было в версии битрикса 6.5 Использование универсальных компонент дало следующие преимущества:
Они были написаны под конкретные задачи и были достаточно лаконичными
Оптимизация компонента давала выигрыш сразу во всех местах, где использовался этот функционал
Новые возможности становились доступными тоже сразу везде.
Даже новый разработчик мог достаточно быстро собирать разделы без залезания под капот. Всё было унифицировано.
Были и грабли:
Сопровождение, проверка всех возможных вариантов использования при модификации отнимали достаточно времени
Ошибка в компоненте могла полностью развалить сайт.
Множились не компоненты, а шаблоны. Граблями это не назвать – просто непривычно.
Если подвести итог, то разработка велась под девизом: если можно – используем типовые компоненты, а если их нужно кастомизировать, то используем «универсальные».
Поскольку в них примерно на год раньше битрикса появилась выборка связанных данных и прочие вещи, с которыми частенько сталкивались разработчки, то они были на тот момент действительно удобны. При их разработке я допустил ряд ошибок и могу теперь признать, что они морально устарели.
Сам подход я считаю жизнеспособным. Поэтому решил сделать второй подход к станку. Уже с учётом своих шишек и консультируясь с комьюнити. Результаты работы естественно тоже будут открытыми и свободными для любого разработчика.
Какие подходы есть сейчас Универсальные компоненты Антона Долганина Почитать описание можно в статье «»
Основные моменты:
Легковесные компоненты
Есть обёртка в виде комплексного компонента.
Исходный код закрыт
Нетиповой функционал по скриншотам не видно J
Антон, что я забыл?
Минималистичный компонент от Ивана Левого Посмотреть описание можно в статье «» Основные моменты:
Компонент полностью «вырожден» Осталось только кеширование. Вся логика пишется в result_modifier.php
Предполагает своё использование в том случае когда нужно писать с 0, а не кастомизировать.
Исходный код есть.
Свои старые наработки Могу показать только скриншот настроек компонента списка. Для детального – попроще. И описать основные моменты. Основные моменты:
Всё начиналось как легковесный компонент…
Компоненты могут получать данные (поля, свойства, цены) из связанных ИБ и это полностью настраивается. Для каждой связи типа Е в головном элементе строится отдельный GetList и данные добавляются в arResult
Гибкие настройки фильтрации данных (из переменной, из настроек компонента)
Отладочные сообщения позволяют посмотреть, что получилось в результате наклацывания всех этих галочек.
Работа в режиме торгового каталога и интернет-магазина.
Отладочный шаблон, который позволяет посмотреть что пришло в arResult без написания var_dump.
По факту – можно считать их морально-устаревшими. Хотя на момент их написания – они на голову делали типовые компоненты.
Что хочу сделать С чистого листа переписать универсальные компоненты. Сделать их гораздо легче и лаконичнее. Часть функционала оказалась попросту лишней в 50% случаев.
Сначала хочу сделать простые список и детальную, потом сделать для них комплексную обёртку. В первой версии они будут беднее чем компоненты news.*
Что вам не хватает в типовых компонентах news.*? Я не обещаю что всё что будет написано будет реализовано. Да и стараюсь уйти от «панели управления самолётом» в настройках компонента.
Когда будет что показать – сделаю сравнение с компонентом news.list как по функциональным возможностям, так и по удобству для разработчика и быстродействию.
Поскольку пишу в свободное от работы время, то на быструю реализацию и интерактивность рассчитывать не стоит. Делаю не только под свои нужды, поэтому идеи приветствуются.
Все наверное знают такую выпадашку-список с возможностью ввести произвольный запрос, и будут подгружены новые данные. Ну так вот сделал такую штуку для любых данных (инфоблоки, местоположения, и так далее) системы Битрикс, выкладываю в общее пользование.
Товарищи! Бойцы софта и харда! Поздравляю вас с профессиональным праздником! Всём желаю профессионального роста, много хороших дивайсин/софтин (кому что ), мало тупых юзеров, и конечно счастливой жизни!
Пока Битрикс не выпустил обновление, решающее эту задачу, опишу костыль для решения на коленке.
Проблема: товары родители в торговом каталоге c SKU не имеют цены и потому не попадают в выгрузку.
Решение: получить цену (в данном случае - минимальную) для торгового предложения (которое есть в наличии) данного товара
Примечание: данное решение подходит для случая, когда все торговые предложения данного товара выводятся на одной странице - мы берем только одно предложение, чтобы не дублировать URL. Для случая, когда предложения на разных страницах - надо генерировать отдельные offers со своими уникальными URL
Оказывается в настройках карты сайта (Настройки > Настройки продукта > Настройки модулей > Главный модуль > Карта сайта) можно через запятую указать несколько типов меню, из которых будет строится карта.
Полезная мелочь за номером два. Представим себе обычную ситуацию - есть инфоблок, элементы которого через свойство ссылаются на элементы второго. Например, товары ссылаются на справочник брендов. И вот мы выводим список товаров, но при этом нам хочется, чтобы в этом списке также отображались и названия (а также, возможно, логотипы) брендов.
Что делают нормальные люди? Они кладут, не побоимся этого слова, нужный компонент для списка товаров, проверяют, как они отобразились, потом копируют стандартный шаблон в нужное место для того, чтобы его перекурочить под дизайн сайта. А затем они пишут result_modifier для этого шаблона, в котором делают цикл а-ля:
foreach ($arResult["ITEMS"] as $key => $arItem):
// А не хапнуть ли нам данные о брендах? Конечно, хапнуть!
// Мы модные пацаны, поэтому вместо стандартного GetByID будем
// использовать реальный CNCodenails::IBElementGetById !
$arResult["ITEMS"][$key]["BRAND"] = CNCodenails::IBElementGetById($arItem["PROPERTIES"]["BRAND"]["VALUE"], array("NAME", "PROPERTY_LOGO"); endforeach;
За счет CNCodenails::IBElementGetById это уже лучше, чем могло бы быть (и чем было у нас до того, как мы осознали проблему с GetByID), но это не самое лучшее в некоторых ситуациях. Снова на помощь партнерам 1С-Битрикс пришел Черный Плащ - Денис Шаромов! Пролетая над нашим кодом он, в частности, грустно спросил: "Зачем же ты, рядовой Иванов, капаешь раскаленным оловом на своего боевого товарища?" (с) старый анекдот.
Что означало - код неоптимальный. А более оптимальный код в данном случае означал бы сведение цикла из запросов к одному запросу при помощи волшебного метода GetList, который умеет вытаскивать элементы по массиву значений, в частности, по массиву идентификаторов. Код, соответственно, будет выглядеть несколько иначе:
Если посмотреть в режиме отладке на получившиеся запросы, то мы увидим, что он и правда будет один и выглядит наподобие следующего:
SELECT BE.ID as ID,BE.NAME as NAME, FPV0.VALUE as PROPERTY_ISBN_VALUE, FPV0.ID as PROPERTY_ISBN_VALUE_ID
FROM
b_iblock B
INNER JOIN b_lang L ON B.LID=L.LID
INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID
LEFT JOIN b_iblock_property FP0 ON FP0.IBLOCK_ID = B.ID AND FP0.CODE='BRAND'
LEFT JOIN b_iblock_element_property FPV0 ON FPV0.IBLOCK_PROPERTY_ID = FP0.ID AND FPV0.IBLOCK_ELEMENT_ID = BE.ID
WHERE
1=1 AND ( (((BE.ID IN ('53', '54', '57')))) ) AND (((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL)))
В общем-то вывод на текущий момент простой: 1. Если нужны поля/свойства одного элемента, лучше использовать CNCodenails::IBElementGetById вместо CIBlockElement::GetByID. 2. Если нужны поля/свойства нескольких элементов по известным идентификаторам, лучше использовать GetList и массив в качестве значений для поля "ID".
Я давно уже понял, что «самописные» решения — прямой путь к дорогому и неудобному владению сайтом…
С точки зрения бизнеса веб-студий, создание и развитие сайта на собственной системе управления — это возможность «подсадить» клиента на свою систему и потом брать с клиента деньги за малейшие изменения. Я даже слышал, как бизнес-тренер, который специализируется на продажах в области веб-разработки рекомендовал такой подход, но его освистало профессиональное сообщество и ему пришлось «признаться», что это была просто неудачная шутка. Дело в том, что это еще и гарантия, что клиент не уйдет от вас, будет терпеть просрочки и неудобства, ведь единственная возможность прекратить такие отношения — перевести сайт на отчуждаемую от разработчика систему, что по цене близко к полной переделке сайта (за минусом дизайна и иногда верстки). Не каждый решится на этот шаг, особенно, если сайт худо-бедно все-таки работает и приносит результат.
К сожалению, заказывая первый раз разработку сайта, не все знают об этой опасности и попадают в зависимость от одного разработчика. Самое печальное, если такой разработчик и вовсе отказывается что-то разработать (не хочет/не может/не умеет), либо исчезает с рынка. На нашем опыте мы неоднократно сталкивались с такими случаями.
Я не буду называть конкретные названия студий, кто так работает, на сегодня это три Архангельские веб-студии и некоторые частные разработчики. Самой популярной отчуждаемой системой у Архангельских веб-студий является 1С-Битрикс, на 2-м месте системы Joomla!, Wordpress и Drupal, которые очень сильно уступают по функционалу и удобству системе 1С-Битрикс.
На днях для одного из своих проектов мы заказали проверку в Экспертной лаборатории
Опыт оказался полезным хотя бы с той точки зрения, что Денис Шаромов в процессе анализа поделился одним простым выводом из опыта Битрикс в борьбе за производительность. Кэширование компонентов - по своей сути, не решает задачи производительности как таковую, а помогает при масштабировании, увеличении нагрузки и т.д. То есть, если в коде есть мелкие косяки - лишние запросы, которых можно было бы при разработке избежать, то кэширование поверх этих запросов проблему решает не всегда. Для нас это было несколько неожиданно, поскольку в общем-то, мелкие запросы, как нам казалось, не сильно влияют (в относительной оценке) на работу сайта, если при этом на том же сайте есть какой-нибудь явно тяжелый кусок, связанный, например, с фильтрацией товаров, который по определению кэшированию не поддается.
Тем не менее, вычистка парочки таких мелких кусков позволило почти сразу довести проверяемый проект до состояния "непадучести". Поэтому сейчас мы более тщательно смотрим на мелкую оптимизацию кода.
О чем речь?
Признаемся себе - достаточно часто в проектах многие используют вызов CIBlockElement::GetById. Простой, удобный метод когда нам надо вытащить какое-то поле для элемента инфоблока. Фигня же в том, что этот метод тянет все поля и все свойства элемента и в случае инфоблока с большим кол-вом свойств, а также предположении, что на сайте вагон посетителей, превращает этот простой запрос в небольшую дырку в производительности. А теперь представим, что у нас таких дырок несколько десятков в различных result_modifier у разных компонентов и окажется, что в совокупности, несмотря на кэширование, эти вещи создают пиковые нагрузки в момент обновления кэша.
Если уж нам надо получить название элемента по ID, то лучше воспользоваться GetList с указанием конкретного вытаскиваемого поля элемента.
Для себя мы написали функцию-затычку, поскольку прямое использование GetList требует определенной писанины. В базовом модуле cn_codenails (который содержит, кстати говоря, ряд некоторых мелких халявных полезняшек) есть метод IBElementGetById, которому передается идентификатор элемента и перечень полей, которые нам надо получить в результате.
Простое сравнение со включенным монитором запроса показывает значительную разницу в выполнении стандартного метода GetById и метода IBElementGetById:
Но после какого-то недавнего обновления для прозрачных изображений начал появляться черный фон вместо прозрачных пикселов.
Полез в ядро. В общем, если кратко, добавилась поддержка фильтров для изображений. И в результате вызова функции таким образом, как показано выше, к вашему изображению, применяется вот такая штука
Обычно, события статистики работают с рекамными компаниями (баннерами). Но зачастую удобно смотреть CTR какого-либо явления (показ кнопки и нажатия на нее) не оформляя все это как баннеры. Для этого достаточно в /bitrix/php_interface/init.php вписать строки такого рода:
Вышло готовое решение с соц. сетью и я заметил, что дизайн там поприятней. Захотел свой старый сайт обновить, взяв дизайн из нового решения. Оказалось, что для меня это было не просто. Даже служба поддержки тут не помогла.
Я хотел поменять вид гаджетов с синих с скруглениями на серенькие. Нашел шаблон гаджета, но дизайн задается не от туда, как оказалось. В поддержке тоже думают, что он там задается: Дизайн хранится в файле /bitrix/components/bitrix/desktop/template/.default/style.css
Я так тоже думал, но оказалось не так. В том файле действительно заданы стили, но они перебиваются данными из следующих 3 файлов, в каждом по чуть-чуть: