Итак функциональные возможности приложения: 1. Работа в offline режиме 2. Автоматическое обновление без перезаливки сборок в google Play и App Store 3. Пуш уведомления 4. Расширить функциональность можно с помощью плагинов =
Документация cordova - Документация fraimework7 -
Надстройка под битрикс, со всем готовым 1. Устанавливаем модуль 2. Создаем папку для мобильного приложения на сайте /mobile_app/ 3. Размещаем в ней компонент и web версию мобильного приложения 4. Меняем стартовый адрес на свой в 5. Приложение готово к использованию, протестировать на android можно тут , указав в настройках стартовый адрес 6. Если по каким-то причинам была допущена ошибка в адресе, то придется переустановить или очистить данные в приложении
Структура шаблона, браузерная версия, и механизм работы 1. Файлы в /mobile_app/www/ должны быть расчитаны на то, что не будут изменяться. Иначе для их изменения потребуется перезаливка сборок в маркеты 2. js/app.js - настройка которая понадобится для браузера и для разработки browser: true (не загружает js и css а берет напрямую с сервера, чтобы не обновлять постоянно базу) - для сборки приложения тут будет browser: false - логика скрипта заключается в создании базы и загрузке в нее данных: шаблон html, шаблоны страниц, оффлайн страницы, меню, кастомные стили, кастомный js 3. в качестве базы используется web sql 4. также для index.html используются прямые подключения файла js и css, при сборке нужно убирать
Подробно по файлам: ajax.php - это запросы по url=/ajax/$page/, $page = /pages/$page.php css.php - получение кастомного файла стилей, по умолчанию грузит из /custom/main.css js.php - получение кастомного файла скриптов, по умолчанию грузит из /custom/main.js menu.php - меню приложения pages.php - список страниц для загрузки в базу, а также их содержание приложение отправляет запрос /page/ шаблон отдает список страниц после приложение поэтапно шлет запросы на получение данных, идентификаторы содержаться в $arResult['VARIABLES']['GET_PAGES'] эти данные пишутся в базу в приложении в json tmpl.php - шаблоны страниц приложения, получает из папки /tmpl/ version.php - версия приложения, при изменении версии обновит данные у всех автоматически при запуске и наличии интернет
папка /pages/ - это online страницы, и скрипты для приемки данных updatepush.php - обновляет идентификаторы пуш, выданные FCM err.php - это страница ошибки если по адресу /ajax/$page - не найдется данных *.php - любые ваши online страницы (при размещении компонентов битрикса, пагинаций, фильтров и т.п. следует учитывать что каждый запрос с приложения подписывается get параметрами, версия, ид устройства, ключ и т.п.)
папка /tmpl/ error.tmpl - страница ошибки при поиске страницы в базе html_page.tmpl - шаблон html страницы main.tmpl - шаблон главной online страницы main_offline.tmpl - шаблон главной offline страницы - *.php - любые шаблоны offline страниц, если страницы статические можно не заморачиваться и размещать их сюда, pages.php получит и загрузит их автоматически Подробно о main.js Файл содержит в себе всб логику вашего приложения, весь код в данном файле выполняется в eval(); в приложении при запуске Основной механизм это подключение fraimework7 + некотороя надстройка для работы с ним и обход некоторых ньансов и механизмов работы библиотеки. есть костыли для отображения кнопки назад, т.к. фреймворк автоматически подгружает предыдущие страницы и некоторые другие ньансы... Основные проблемы это работа истории и кнопки назад (они же были и в версии fraimework7 v.1), скорее из-за особенности оффлайн режима и того что фреймворк не подразумевает что оффлайн данные будут лежать гдето в базе внутри приложения и изменяться со временем
вообщем этот каркас я использую во всех своих приложениях ничего не меняя комментарии в коде кое-какие написал... чтобы понять логику... Сборка приложения в phonegap build 1. Необходимо зарегистрироваться на сервисе 2. Создать реп на git для приложения. Пример: 3. Для пушей добавляем проект в (для отправки с админки битрикса, копируем ключ в настройки модуля). для android приложения скачиваем google-services.json, для ios GoogleService-Info.plist 4. Меняем стартовый url в app.js (меняем изображения и свои стили, если вы их решили добавить) 5. делаем иконки и сплеш экраны (размеры и настройки в config.xml взял из одного из своих проектов). Примеры для phonegap build, также есть на акаунте (правда пока не все переделаны под fraimework7.v2)
Подробнее о добавлении плагинов и параметров для сборки смотрите в документации cordova, и phonegap build
Для андроид можно без ключей сбилдить debug версию в которой все будет работать Публикация приложения: Release версия android требует ключа, как создать можно погуглить (акаунт в google play для публикации единоразово, точно сумму не помню но гдето около 25$) Для ios требуется аккаунт разработчика, создание сертификатов, ключей, провизии происходит через личный кабинет developer.apple.com (стоит 99$ в год, для беларуси накладно с учетом того что юзают приложения не много людей) Конвертация в нужный формат уже через приложение на MAC Keychain Access (самый простой способ), загрузка через application loader Да и без макбука будет тяжеловато грузить сборки, также для тестирования нужно ios устройство (хотя после тестирования на андроид ньансов небыло никаких на ios) Денег на ios технику у меня нет, поэтому я обычно в скайпе попрошайничаю выполнить бесплатно работу тестера По поводу макбука таже история, но можно на vmware развернуть виртуалку хакинтоша, через которую можно загружать приложения Вообще на сам процесс публикации в app store нужно будет набраться терпения и времени Если ктото решит побаловаться и будут какие вопросы можно писать в скайп mlife_development, Если нет андроид устройства но хочется побаловаться то могу собрать тестовую версию приложения и для ios, от вас нужен будет email адрес в app store, для добавления вас в качестве тестера
на данный момент нет поддержки транспорта файлов (но реализация думаю возможно с помощью плагина cordova-plugin-file)
Захотелось сделать для рабочих проектов ssl. Не самоподписной, не платный (сейчас бы в 2018 году за воздух платить), а нормальный бесплатный, от letsencrypt. И чтобы он автоматически продлялся (ибо срок его действия лишь 3 месяца).
Благо, все уже изобретено до нас.
Для развертывания сайта у меня был голый debian с установленными docker и docker-compose (настроенными для выполнения от рядового пользователя).
Сначала создаем docker-compose.yml, описывающий запуск небезывестной связки jwilder/nginx-proxy (реверс-прокси на nginx) и jrcs/letsencrypt-nginx-proxy-companion (certbot по сути). В добавок к ним я добавил популярный portainer/portainer, чтобы можно было мониторить, что происходит с контейнерами, и управлять ими из удобного веб-интерфейса.
// Предварительно создадим сеть
$ docker network create nginx-proxy
// Заведем для всей этой кухни свою папочку, для удобства я назвал и сеть, и контейнер, и директорию одинаково.
$ mkdir nginx-proxy
$ cd nginx-proxy
// Для хранения сертификатов и некоторых автогенерируемых цертботом файлов нам потребуется пара директорий
$ mkdir certs
$ mkdir vhost.d
// собственно файлик с описанием сервисов
$ touch docker-compose.yml
Содержимое файла:
version: "2"
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
# такой лейбл позволит контейнеру с цертботом понять, какой из запущенных nginx - реверс-прокси.
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./vhost.d:/etc/nginx/vhost.d:ro
- /usr/share/nginx/html
letsencrypt-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt-companion
volumes_from:
- nginx-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/etc/nginx/certs:rw
- ./vhost.d:/etc/nginx/vhost.d:rw
portainer:
image: portainer/portainer
container_name: portainer
ports:
- 9000
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/portainer/data:/data
environment:
- VIRTUAL_HOST=portainer.devserver.com
- VIRTUAL_PORT=9000
- LETSENCRYPT_HOST=portainer.devserver.com
- LETSENCRYPT_EMAIL=admin@devserver.com
# по умолчанию подключаем к сети, в которой будут находиться будущие сайты
networks:
default:
external:
name: nginx-proxy
Доменное имя для portainer указано для примера. Единственное условия - чтобы оно было доступно извне для сервисов letsencrypt. Уже по коду этого файла видно, как примерно работает эта связка. Если запустить ее
$ docker-compose up -d
подождать, пока сгенерируется сертификат (обычно около 1-2 минут), то можно уже заходить по адресу, который мы указали в переменной VIRTUAL_HOST и увидеть работающий portainer. Причем уже по протоколу ssl. Если нажать на зеленый замочек, то мы увидим, что это действующий сертификат от letsencrypt.
Далее можно создавать контейнеры с помощью портейнера, а можно пойти более "простым" путем. Принцип подключения сайтов к виртуальной сети, в которой крутится reverse-proxy и certbot, остается тот же - использование переменных VIRTUAL_HOST, LETSENCRYPT_HOST и LETSENCRYPT_EMAIL.
Например, это простенький docker-compose.yml, описывающий связку сервисов для запуска битрикса:
version: '2.1'
# сеть по умолчанию - та же, что и сеть реверса и цертбота
networks:
default:
external:
name: nginx-proxy
### Services
services:
nginx:
image: nginx:${NGINX_VERSION}
container_name: ${PROJECT_CODE}_nginx
environment:
- VIRTUAL_HOST=$PROJECT_DOMAIN
- LETSENCRYPT_HOST=$PROJECT_DOMAIN
- LETSENCRYPT_EMAIL=$PROJECT_EMAIL
volumes:
- "${PROJECT_PATH}:/var/www/html/:ro"
## тут можно пробросить в контейнер нужные вам конфиги, например правильно указанный upstream
- "./nginx/project.conf:/etc/nginx/sites-available/project.conf:ro"
- "./nginx/upstream.conf:/etc/nginx/conf.d/upstream.conf:ro"
links:
- php
php:
image: alterway/php:${PHP_VERSION}-${BACKEND}
container_name: ${PROJECT_CODE}_php
environment:
- PHP_php5enmod=mcrypt memcached mysqli opcache gd mbstring soap zip
- PHP__date.timezone
- PHP__display_errors
- PHP__log_errors
- PHP__magic_quotes_gpc
- PHP__memory_limit
- PHP__upload_max_filesize
- PHP__post_max_size
- PHP__max_execution_time
- PHP__mbstring.func_overload
- PHP__mbstring.internal_encoding
- PHP__opcache.enable
- PHP__opcache.revalidate_freq
- PHP__opcache.validate_timestamps
- PHP__opcache.memory_consumption
- PHP__opcache.max_accelerated_files
- PHP__realpath_cache_size
- PHP__max_input_vars
volumes:
- "${PROJECT_PATH}/:/var/www/html/"
db:
image: mysql:${MYSQL_VERSION}
container_name: ${PROJECT_CODE}_db
volumes:
## это чтобы не потерять базу после перезапуска контейнера
- "${VOLUMESDIR}/db/:/var/lib/mysql/"
## тут можно пробросить в контейнер нужные конфиги и прочее
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
memcached:
image: memcached:${MEMCACHED_VERSION}
container_name: ${PROJECT_CODE}_mem
volumes:
## это чтобы не потерять кэш после перезапуска контейнера
- "${VOLUMESDIR}/cache/:/var/lib/memcached/"
База хранится на хосте в .volume/db, мемкэш - в .volume/cache, сайт в www. Как-то так.
После чего, делаем запуск этих сервисов
$ docker-compose up -d
Ждем, пока сгенерируется сертификат для новоиспеченного сайта, скачаются и соберутся образы, запустятся контейнеры, и можно открывать сайт в браузере (предварительно конечно прописав в .settings.php подключение к БД, где хостом будет название сервиса, в вышеприведенном случае - db; а параметрами подключения - значения из переменных .env-файлика).
И этот сайт сразу будет доступен по https с сертификатом от letsencrypt.
Алгоритм этой связки достаточно прост. В общих чертах если, то сервис nginx-proxy следит за появлением в сети новых сервисов с переменной VIRTUAL_HOST, и создает для них конфигурации server, подключает и запускает. Что позволяет пробиться к сервисам сквозь прокси. Помощник letsencrypt таким же образом следит за сервисами с переменными LETSENCRYPT_ и генерирует для них сертификаты на соответствующее доменное имя. Попутно он дописывает конфигурации server у nginx-proxy, чтобы обеспечить подключение этих самых сертификатов и работу по https. Плюс, раз в час этот помощник проверяет, не устарели ли сертификаты, и генерирует их по новой, если надо.
или помогите разобраться в почему стал ошибку выдавать Parse error: syntax error, unexpected 'Y' (T_STRING), expecting ')' in /................./index.php on line 40
Добрый день! помогите - рухнула главная страница после внесения изменения в визуальном редакторе - как откатить изменение в админке? воскресить до сохранения главную страницу
сейчас не дает зайти - пишет ошибку в странной строке
Если у вас есть коробочная версия Битрикс24, и вы хотите использовать живую ленту, мгновенный чат, и получать push уведомления на телефон — вам понадобится модуль push and pull.
Сообщение "Отсутствует соединение с сервером" - говорит о проблемах с модулем push and pull. Трудности с настройкой этого модуля регулярно возникают у многих.
Судя по всему, настройка модуля push and pull не имеет тривиального решения, и исчерпывающего руководства, собранного в одном месте. Попробую исправить ситуацию.
Добрый день, всем! Нужно сделать интернет - магазин на Битриксе. Тема: "Продажа оборудования, орг. техники и телефонов". Кто может помочь, скиньте, пожалуйста, ваше предложение и интересующие вас вопросы. Спасибо!
Есть некий фрилансер и есть заказчик, с которым данный фриласер работал около двух лет. Изредка выполняет задачи по сайту. В один прекрасный день владелец сайта заходит в панель управления вдс и переустанавливает операционку случайно. Естественно удаляет вообще весь сайт. Фрилансер неделю его восстанавливает и по прошествии недели заказчик просит скидку на работу, аргументируя это тем, что фрилансер должен был делать бэкапы в нескольких местах. Поставьте пожалуйста галочку в форме ниже, должен ли фрилансер заплатить штраф (уменьшисть стоимость работ, предоставить скидку)
Задача по бэкапам была давно - звучала как "делать бэкапы". По мнению заказчика само слово бэкап подразумевает то, что он делается в нескольких местах и проверять эту задачу не нужно и так все ясно. Фрилансер же считает, что он не технический директор, не человек заинтересованный в работе сайта, а просто человек, который делает задачи. В данном случае он не проявил инициативы и все.
Добрый день всем! Подскажите, пожалуйста, кто сможет помочь с таким вопросом: на сайте интернет магазина можно ли в карточке товара сделать так, чтобы помимо количества товара можно было бы еще выбирать и размер товара и этот размер, также, как и количество, попадал бы в корзину и считалась сумма?
Иерархия папок и файлов с обработчиками внутри HelperEventHandlers следующая:/HelperEventHandlers/[модуль]/[событие]/[название, которое можно было бы дать обработчику при классическом расположении, т.е. в init.php или handlers.php ].php
Пример файла FixIBlockPermissions.php с обработчиком:
/**
* перед добавлением инфоблока
*
* даем права на инфоблоки на чтение по умолчанию
*/
AddEventHandler("iblock", "OnBeforeIBlockAdd", "iblock_OnBeforeIBlockAdd_FixIBlockPermissions");
function iblock_OnBeforeIBlockAdd_FixIBlockPermissions(&$arFields) {
$filter = array();
$rsGroups = CGroup::GetList(($by = "c_sort"), ($order = "desc"), $filter);
while ($arGroup = $rsGroups->Fetch()) {
if ($arGroup['ANONYMOUS'] == 'Y') {
$group_id = $arGroup['ID'];
break;
}
}
$arFields['GROUP_ID'][$group_id] = "R";
}
Название обработчика формируется по следующей схеме: [модуль]\_[событие]\_[название, которое можно было бы дать обработчику при классическом расположении, т.е. в init.php или handlers.php]
После установки этого пакета EventHandlersLoader.php подключается в init.php Там же используем следующий метод:`EventHandlersLoader::includeEventHandler();` - подключение всех обработчиков `EventHandlersLoader::includeEventHandler("iblock_OnBeforeIBlockAdd_FixIBlockPermissions");` - подключение обработчика iblock_OnBeforeIBlockAdd_FixIBlockPermissions
Посмотреть список доступных обработчиков можно при помощи метода `EventHandlersLoader::getEventHandlersInfo();`
Содержимое EventHandlersLoader.php :
class EventHandlersLoader
{
/**
* @param $strHandlerName
* подключение обработчика события
*/
public static function includeEventHandler($strHandlerName)
{
if ($strHandlerName) {
$arHandlerName = explode("_", $strHandlerName);
require_once(__DIR__ . '/HelperEventHandlers/' . $arHandlerName[0] . '/' . $arHandlerName[1] . '/' . $arHandlerName[2] . '.php');
} else {
$directory = new \RecursiveDirectoryIterator(__DIR__ . '/HelperEventHandlers/');
$iterator = new \RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
if ($info->getFilename()[0] === '.') continue;
require_once ($info->getPathname());
}
}
}
/**
* @param string $inEncode
* @param string $outEncode
* список доступных для подключения обработчиков событий
*/
public static function getEventHandlersInfo($inEncode = "utf-8", $outEncode = "windows-1251"){
$directory = new \RecursiveDirectoryIterator(__DIR__ . '/HelperEventHandlers/');
$iterator = new \RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
if ($info->getFilename()[0] === '.') continue;
$fileContent = file_get_contents($info->getPathname());
$tokens = token_get_all($fileContent);
echo iconv($inEncode, $outEncode, $tokens[2][1]) . "<br>" . $tokens[12][1] . "<hr>";
}
}
}
Авторизация через социальные сети в Битрикс выдает ошибку. Как это исправить? Идем в админку, Настройки - Настройки продукта - Настройки модулей - Главный модуль - Авторизация и снимаем галочку "Запрашивать подтверждение регистрации по E-mail", ставим галочку "Позволять ли пользователям регистрироваться самостоятельно?". И вуаля, авторизация через любую социальную сеть работает
Подключение нового фильтра bitrix:main.ui.filter для пользовательских форм.
Данный фильтр работает в связке с гридом bitrix:main.ui.filter. У меня стояла задача прикрепить для своих пользовательских форм, где нет необходимости в использовании грида.
Рассмотрим кратко, как можно использовать данный компонент.
Вначале создадим массив с полями. Детально о вариантах полей Вы можете узнать в исходнике компонента.
Есть в битриксе всеми любимая функция - CFile::ResizeImageGet. Но что делать, если необходимо изменить размер фото, не обрезая видимую честь, а добавляя к ней поля?
К сожалению такого способа кадрирования в ResizeImageGet и битриксе вообще нет (или я ошибаюсь?) Поэтому будем писать костыль.
Задача; Кадрировать фото под заданный размер, с сохранением пропорции, добавляя необходимые поля. Решение: Использовать ResizeImageGet два раза Код;
<?
// проверим, есть ли картинка, которую будем кадрировать
if ($arResult['ITEM']['PREVIEW_PICTURE']['ID']>0){
// Зададим размер выходной картинки
$width = 300;
$height = 300;
// Кадрируем картинку, с сохранением пропорции.
$image = CFile::ResizeImageGet(
$arResult['ITEM']['PREVIEW_PICTURE']['ID'],
array("width" => $width, "height" => $height),
BX_RESIZE_IMAGE_PROPORTIONAL,
true,
false,
false,
100 // качество сжатия выходного файла должно быть 100, чтобы избежать лишних потерь качества.
);
// Проверяем, прошло ли кадрирование. Если нет, то берем изначальное изображение.
if (strlen($image['src'])<3){$image['src']=$arResult['ITEM']['PREVIEW_PICTURE']['SRC'];}
// А теперь накладываем на прозрачный фон нужного размера, изначальную картинку, используя фильтр watermark
$arWaterMark = Array(
array(
"name" => "watermark",
"position" => "center",
"type" => "image",
"size" => "real",
"file" => $_SERVER['DOCUMENT_ROOT'].$image['src'], // Путь к картинке полученной в первом вызове CFile::ResizeImageGet
"fill" => "exact",
)
);
$file = CFile::ResizeImageGet(
5145, // id файоа с прозрачным фоном в b_files
array("width" => $width, "height" => $height),
BX_RESIZE_IMAGE_EXACT,
true,
$arWaterMark,
false,
100 // Тут можем менять качество конечной картинки, для оптимизации размера страницы
);
// Заменяем начальную картинку, на полученную.
$arResult['ITEM']['PREVIEW_PICTURE']['SRC'] = $file['src'];
$arResult['ITEM']['PREVIEW_PICTURE']['WIDTH'] = $file['width'];
$arResult['ITEM']['PREVIEW_PICTURE']['HEIGHT'] = $file['height'];
}
?>
Комментарии: Основная магия в хардкоде 5145 второго вызова CFile::ResizeImageGet. Это файл с прозрачным (или любым другим) фоном, для создания полей. Он должен быть больше, чем конечное изображение, иначе второй вызов CFile::ResizeImageGet( не отработает. Файл был залит в медиабиблиотеку, после чего его ID был получен из таблицы b_files. Обращаю внимание, что тут нельзя использовать прямую ссылку на картинку.
Данный код можно поместить к result-modifier.php для обрезания на лету или в обработчик события для для сохранения его вместо изначального.
Заключение: Если кто-то предложит более правильный способ решения этой задачи, прошу опубликовать его в комментах, т.к. заказчик часто просит именно такой вариант кадрирования, с добавлением прозрачных полей.
Здравствуйте, необходимо создать сайт на Bitrix на примере другого сайта, хотелось бы получить примеры ТЗ, бриф от разработчиков, чтобы понять кто сможет осуществить данную задачу и почем.
Для систематизации активных проектов, а также для быстрого старта новых в недрах компании был разработан шаблон-заготовка, содержащий много полезностей для эффективной работы:
Что проект может предложить искушенным битрикс-девелоперам:
"Безопасная" структура
Конфиги, гит-директория, вендорные файлы находятся аж на 2(!) уровня выше веб-директорий.
"Готовность" к многосайтовости.
Зачастую (особенно, когда гит инициализируют в корневой веб-директории) добавление второго сайта под версионный контроль становится непростой (и внезапной) задачей. В нашем случае эта проблема решена на архитектурном уровне. Проект изначально стартует в структуре, подразумаевающей наличие нескольких сайтов.
Композер "из коробки".
Помимо очевидной автозагрузки, и подключения сторонних библиотек общего назначения, также становится возможна установка Битрикс-модулей из Packagist и публичных/приватных репозиториев (благодаря пакету composer installers)
Базовые Битрикс компоненты.
Тут достаточно ознакомиться с описанием и документацией, чтобы захотеть использовать данный модуль.
Шаблонизатор Twig
Данный пакет позволяет снизить количество копипасты файлов шаблонов при создании и наследовании компонентов, а также более явно разделить слои контроллера и отображения (Иными словами использовать Bitrix API в шаблоне становится намного сложнее).
Огромные возможности по работе с данными "из коробки" и простой механизм расширения.
Миграции
Тут все просто и понятно. Библиотека предоставляет необходимый набор функций для работы с миграциями данных.
Модели.
Удобный способ работы с основными сущностями Битрикс. Бонусом получаем возможность использовать Eloquent-модели как альтернативу D7 ORM.
Консольный джедай.
CLI-интерфейс для Битрикса. Много полезных функций из коробки и возможность написания своих собственных команд.
Подробней:
Логгирование.
Никаких AddMessage2Log() в корень сайта . Используется уже "стандартный" для многих фреймворков логгер Monolog.
Фронтенд.
Работа с клиентской частью в Битрикс, мягко говоря, немного отстает от современных реалий веб разработки. Поэтому управление фронтом решено было делегировать более подходящему инструменту.
Для сборки фронтенда используется модуль Webpack Encore
Который как следует из названия является настройкой над Вебпаком.
Он позволяет относительно легко настроить работу с актуальным стеком технологий.
В нашем случае это:
6 Редакция Javascript (ES6)
VueJS для "сложного-богатого" фронтенда
SCSS и БЭМ для организации работы со стилями
Версионирование и деплой.
Чтобы релизить как можно чаще и быть уверенным, что все будет пернесено, собрано, установлено как надо, используется утилита для автоматизированного деплоя
При использовании системы контроля версий также крайне желательно придерживаться некоторых правил, чтобы не замусорить проект и быть уверенным в коде, что находится на "боевом окружении"
Как выводить первыми те элементы, у которых свойство равно заданному значению?
Заданное значение меняется динамически(выбирается посетителем) Например, мы сортируем по названию по возрастанию, но нужно вывести первыми элементы на букву Ж, а далее как обычно. Или, например, свойство город у товара, которое равно городу посетителя вывести первыми, а далее остальные товары. Речь идет о getList или компонентах вроде catalog, news.
При разработке компонентов и модулей часто приходится делать отладку, а именно вывести содержимое массива. Для удобства можно подготовить несколько готовых функции:
//Функция отладки
function arDump(&$data,$defaultUserId = "1"){
global $USER;
if($USER->GetId() == $defaultUserId){
echo "<pre>".print_r($data,true)."</pre>";
}
}
//Функция Reflection API, получение всех методов, и свойств
function classDump($className,$defaultUserId = "1"){
global $USER;
if($USER->GetId() == $defaultUserId){
$reflection = new ReflectionClass($className);
$methods = $reflection->getMethods();
$props = $reflection->getProperties();
$statics = $reflection->getStaticProperties();
$arReflection["NAME"] = $className;
$arReflection["METHODS"] = $methods;
$arReflection["PROPERTIES"] = $props;
$arReflection["STATIC_PROPERTIES"] = $statics;
echo "<pre>".print_r($arReflection,true)."</pre>";
}
}
//Функция отладки в файл
define("LOG_FILENAME", $_SERVER["DOCUMENT_ROOT"]."/log.txt");
function fileDump(&$arFields,$paramName = "arrName"){
AddMessage2Log($paramName.' = '.print_r($arFields, true),'');
}
Данный код необходимо добавить в файл /local/php_interface/init.php
arDump - выводит содержимое массива в форматированном виде;
fileDump - дозаписывает содержимое массива в файл log.txt в корень сайта. Вместо AddMessage2Log можно использовать аналог в новом ядре D7 - и . Данный вариант отладки очень удобно использовать в ajax запросах.
classDump - можно использовать рефлекию, для того чтобы исследовать недокументированный класс, чтобы посмотреть, какие есть у него методы и свойства.
В фильтр добавляем поле "ZOMBIE" => false. Битрикс задачи из базы на самом деле не удаляет, а просто помечает поле "ZOMBIE" => true и задач не видно в списке. Данный метод вытаскивает все задачи, поэтому и фильтруем.
"STATUS" => self::TASK_COMPLETED - здесь происходит фильтрация по статусу задач.
В сообществе Битрикс уже рассказывали про модальное popup окно. Иногда нужно реализовать простое всплывающее меню как представлено ниже. Сейчас поговорим о том, как его вывести.
Для это достаточно написать нижеприведенный код:
var menu = [];
menu.push({
text: "Бизнес процессы",
title: "Бизнес процессы",
href: "/company/personal/bizproc/"
});
menu.push({
text: "Сервисы",
title: "Сервисы",
href: "/services/"
});
var params = {
offsetLeft: 20,
closeByEsc: true,
angle: {
position: 'top'
},
events: {
onPopupClose : function(){
//обработка событии при закрытии меню
}
}
}
var popupMenu = new BX.PopupMenuWindow(
"myPopupForm",
BX("menuBtn"),
menu,
params
);
popupMenu.popupWindow.show();
"myPopupForm" - строка - уникальный id DOM-элемента; BX("menuBtn") - параметр «принадлежности окна» к какому-либо DOM-элементу на странице (то есть относительно какого элемента будем выводить всплывающее меню); menu - собственно массив объектов с элементами меню; params - параметры окна, аналогичные в .
Заказчик попросил сделать ограничение по размеру загружаемой картинки. Всё просто, если картинка больше минимальной. Её просто обрезаем под размер. При этом делаем это в result-modifier шаблона, на не в настройках ИБ, чтобы всегда можно было получить изначальную картинку. Но что делать, если картинка меньше заданного размера? Заказчик хочет, чтобы загрузить такую картинку было нельзя. Кроме этого необходимо вывести сообщение об ошибку в стандартном интерфейсе битрикса. К сожалению, встроенного механизма для решения этой задачи, в битриксе нет, поэтому будем желать обработчик события.
Задача: При сохранении элемента инфоблока, проверять размер картинки и сообщать, если картинка меньше заданного размера.
Решение: Написать обработчик на событие OnBeforeIBlockElementAdd и OnBeforeIBlockElementUpdate в котором проверять размер и выдавать исключение если картинка не маленькая.
Код:
class image{
function checkSize(&$arFields) {
// инфоблок, в котором проводить проверку.
$iblockId = 4;
// минимальная ширина
$width = 300;
// минимальная высота
$height = 300;
// массив ошибок
$errors = false;
// проверяем, инфоблок, в котором сохораняется картинка.
if($arFields["IBLOCK_ID"] == $iblockId) {
// получаем размеры временного файла
$file = CFile::GetImageSize ($arFields['DETAIL_PICTURE']['tmp_name']);
// если получены размеры.
if ($file !== false && is_array($file)){
// проверяем ширину
if ($file[0] < $width){
$errors[] = 'Ширина изображения должна быть не меньше '.$width.' px. Ширина загружаемого файла '.$file[0].' px';
}
// проверяем высоту
if ($file[1] < $height){
$errors[] = 'Высота изображения должна быть не меньше '.$height.' px. Ширина загружаемого файла '.$file[1].' px';
}
// если были ошибки
if (is_array($errors)){
// выдаём исключение с сообщением об ошибке
global $APPLICATION;
$APPLICATION->throwException(implode("<br>", $errors));
// возращаем false, чтобы не сохранять инфоблок
return false;
}
}
}
}
}