Блог Никиты Самохвалова, обо всём и ни о чём.

Позднее Ctrl + ↑

Нововведения и правки «Композер-инсталлера»

Недавно поработал над «Композер-инсталлером»: исправил ошибку в «битриксовом» установщике и добавил доступ к консоли. Что характерно, последняя доработка потребовалась для первой.

Доступ к консоли

В Composer\Installers\BaseInstaller добавлено свойство $io, реализация IOInterface. Отныне можно в консоль выводить уведомления, сообщения об ошибках и даже реагировать на действия пользователя. Парочка примеров:

class BitrixInstaller extends BaseInstaller
{
     protected function templatePath($path, array $vars = array())
     {
          $this->io->writeError('<error>Не хочу устанавливаться!</error>');

          while (true) {
                switch ($this->io->ask('<info>Нажми на клаву [y,n,?]</info> ', '?')) {
                    case 'y':
                        // Пользователь ввёл «y»
                        break 2;

                    case 'n':
                        // Пользователь ввёл «n»
                        break 2;

                    case '?':
                    default:
                        // Пользователь ввёл фиг знает что
                        break;
                }
     }
}

Исправления «битриксового» установщика

Для «Композера» существует установщик «битриксовых» пакетов, который умеет размещать в нужные каталоги сайта модули, компоненты и шаблоны. В первой версии установщика «косяк», нарушающий идеологию «Композера»: пакеты размещались в каталоге local/. Почему это неправильно — расскажу чуть ниже.

Пару дней назад я исправил это, добавив ко всему поиск пакетов-дубликатов в local/. «Композер» любезно сообщит и предложит удалить пакеты из старых путей:

И зачем?..

Вообще-то, на сайте «Композера» об этом написано, но всё равно довольно часто слышу и читаю подобные вопросы. Идеология менеджера пакетов такова, что устанавливаемые библиотеки не должны находится под версионным контролем проекта («Гит», «Меркуриал» и пр.), менеджер сам будет управлять ими и отслеживать их изменение. В проекте должны версионироваться только конфигурационные файлы, в случае «Композера» — это composer.json и composer.lock.

С внедрением в «Битрикс» поддержки отдельной директории local/ для собственных разработок, каталог bitrix/ стал аналогом каталога vendor/. bitrix/ должен использоваться для системных файлов и сторонних модулей, пакетов, тем и пр. Чаще всего, он размещается в .vcsignore проекта.

Ошибка загрузки локальных сайтов в «Хроме»

В 43-й версии «Хрома» появилась какая-то особенность, из-за которой сайты, поднятые локально на доменах вида project.dev перестали открываться: обозреватель возвращает ошибку ERR_ICANN_NAME_COLLISION.

Истинную причину найти не было времени, кто знает — поделитесь. А пока решил проблему заменой .dev на .localhost — единственная зона, с которой «Хром» корректно работает.

2015  

«Адреса сайтов»: перезагрузка

«Адреса сайтов» показали себя с лучшей стороны в боевых условиях: с момента создания ещё альфа-версии я применил их на нескольких многосайтовых проектах, что просто отлично легло на инфраструктуру с разработческими, тестовыми и боевыми серверами. К тому же, хелперы для кешированных выборок данных по сайтам ни раз пригодились для всевозможных проверок и перехватчиков событий.

Но с сегодняшнего дня модуль скрыт из публичной части маркетплейса и уже больше никогда не будет опубликован, и на то есть свои архитектурные причины. На смену ему придёт «Сайтовод» — улучшенная и дополненная версия. Следите за новостями.

P. S. Поддержка «Адресов сайтов» по-прежнему продолжается.

Бета-версия ББК

Большая часть алгоритмов компонентов повторяется. Дублирование кода усложняет поддержку и увеличивает время разработки. Два года назад вендор сделал шаг на встречу — внедрил поддержку ООП в компонентах. Но до сих пор не существует штатного компонента, от которого имело бы смысл наследоваться (компоненты меню и фильтра в расчёт не берём).

Необходимый минимум

Какие типовые задачи обычно выполняет некий абстрактный компонент?

  1. Подключение модулей.
  2. Проверка входящих параметров.
  3. Кеширование.
  4. Генерация строки постраничной навигации.
  5. Установка заголовков страницы.
  6. [Комплексный комп.] Определение запрашиваемой страницы.

Эталон

Продолжим список возможностей абстрактного эталонного компонента:

  1. Оперативное уведомление администратора о  «схваченных исключениях».
  2. Работа с аяксом без лишней головной боли (в обход «битриксовой» технологии).
  3. Установка ОГ-тегов для соцсетей.
  4. Наследование параметров компонентов с возможностью модификации.

Базовые битриксовые компоненты

Всё это должно быть. В смысле, это должно быть написано один раз и применяться на всём проекте. Не копи-пастом, а в виде дочерних классов.

Встречайте «Базовые битриксовые компоненты» — первые, по-настоящему функциональные компоненты для «Битрикса».

Разработчику больше не нужно тратить время на типовые задачи. Задать компоненту собственную логику, сохранив все выше перечисленные эталонные возможности достаточно просто.

Сборка включает в себя два основополагающих абстрактных компонента: basis.router (для комплексных компонентов) и basis (для всех остальных), и компоненты elements.* для работы с элементами инфоблока. У компонентов есть три точки входа, через методы:

  1. executeProlog() — выполняется в начале работы компонента, после подключения модулей, установки параметров и заголовков. Результаты метода не кешируются.
  2. executeMain() — основная логика компонента, все ключевые операции производятся в этом методе. Если в параметрах компонента передан ключ CACHE_TYPE не равный «N», результаты метода буду закешированы.
  3. executeEpilog() — выполняется после подключения шаблона компонента. Результаты не кешируются.

Маленький пример структуры класса, отнаследованного от базового компонента:

<?php

namespace Components\Project;

use Components\Basis;


if(!defined('B_PROLOG_INCLUDED')||B_PROLOG_INCLUDED!==true)die();

\CBitrixComponent::includeComponentClass('basis:basis');


class Test extends Basis\Basis
{
    // Типаж для работы с элементами инфоблоков и различные соцфичи
    use Elements;

    // Модули, которые будут подключены
    protected $needModules = array('iblock');

    // Указываем условия для проверок и приведения параметров
    protected $checkParams = array(
        'IBLOCK_TYPE' => array('type' => 'string'),
        'IBLOCK_ID' => array('type' => 'int')
    );

    public function onPrepareComponentParams($params)
    {
        // Устанавливаем свои параметры, если необходимо

        return $params;
    }

    protected function executeProlog()
    {
        // Выполняем действия в самом начале работы компонента. 
        // Например, можно сохранить какие-нибудь данные, отправленные
        // из формы
    }

    protected function executeMain()
    {
        // Основная логика, метод кешируется. Например, делаем выборку
        // из инфоблока
    }

    protected function executeEpilog()
    {
        // Операции, производимые после подключения шаблона компонента
    }
}

Кроме того, компонент elements.list вызывает на каждой итерации цикла обработки результатов запроса элементов инфоблока метод prepareElementsResult(). С помощью этого метода в дочерних компонентах можно модифицировать обработку результатов выборки: удалять, изменять и добавлять поля, производить какие-либо операции. Метод должен вернуть либо массив полей элемента, либо false для пропуска итерации.

public function prepareElementsResult($element)
{
    if ($element['NAME'] === 'BBC')
    {
        // Пропускаем итерацию, результат не попадёт в arResult
        return false;
    }

    // Обрезаем описание для анонса
    $element['PREVIEW_TEXT'] = substr($element['PREVIEW_TEXT'], 0, 100);

    return $element;
}

Все методы классов задокументированы, компоненты серии elements.* — хороший пример, демонстрирующий возможности сборки, так что смело открывайте свои «идэешки» и наслаждайтесь красотой и умениями ББК. Полноценной документации в онлайне нет, пока только краткое техописание.

Пишите, предлагайте, критикуйте и отправляйте пул-реквесты. Вэлкам!

Базовые битриксовые компонентыβ

P. S. В «Битриксе» много корпоративщины, коммерции. Я не говорю, что это плохо или хорошо, просто пришло время разбавить её. Я приглашаю всех желающих принять участие в развитии ББК, пишите мне на почту или в комментарии.

А надо ли? И если надо, то как?

Часто создатели сайтов пичкают в свои проекты кучу визуальных эффектов и функционала, от чего возникает риск получить сайт с сырым или ненужным функционалом. Возьмём за пример типичные элементы типичного сайта.

Слайдеры, ротаторы и их друзья

Слайдеры, блоки с ротацией контента. У подавляющего большинства есть проблема: что бы переключить слайд, нужно кликнуть по кнопкам управления. Как улучшить? Применить эффект листалки (свайп). Кто-то считает, что листалки нужны только для мобильных устройств. На самом деле, стоит несколько раз попробовать листать слайды на компьютере, как это войдёт в привычку. Листать проще и быстрее, чем прицеливаться и кликать в элементы управления.

Аякс

Порой мало внимания уделяют аяксу. Или наоборот, пытаются применять его везде, где только можно и нельзя. Прежде чем добавлять аякс, стоит задуматься, нужно ли это вообще? Стоит ли тратить время на разработку дополнительного функционала? От этого станет удобнее работать с сайтом?

Сделать обновление данных на странице без перезагрузки — пол дела. Надо помнить, что ответ от сервера на запрос может затянуться или вовсе не прийти, на что клиент должен соответствующим образом реагировать, а не просто «подвисать», оставляя право пользователю гадать о том, что произошло.

Лишние формы

Формы обратной связи не так часто требуются на самом-то деле, как их применяют. Она нужна в тех случаях, когда необходимо отправить заявку в чётко структурированной форме. Если необходима возможность пользователям вступить в переписку с администрацией сайта, какая польза от формы обратной связи? Переписка в итоге будет всё равно вестись по эл. почте, тогда зачем тратить время на создание формы «фидбэка», если можно просто оставить адрес своей почты?

***

Я описал типичные проблемы интерфейсов сайтов, но важно другое. Важно, на мой взгляд, приступая к разработке какого-либо функционала поднимать вопрос: «Как это поможет пользователям?» и продумывать «на берегу» все нюансы реализации.

Многосайтовость в «Битриксе»

Делюсь опытом разработки многосайтов.

Подкаталоги в php_interface

«Битрикс» позволяет создавать для каждого сайта свой php_interface, со своим init.php и подключаемыми файлами. Что это даёт? Как известно, все файлы, подключаемые в init.php, подгружаются на каждом хите. Вынеся всю логику в каталог отдельного сайта, мы снимем необходимость прогружать эти файлы в других сайтах. Хороший тон — использовать эту возможность всегда, даже когда разрабатывается один сайт, потому что никто не гарантирует, что, скажем, через год на том же ядре не появятся новые проекты.

Из консоли идентификатор сайта не определяется и, как следствие, подкаталог не подгружается. Консольные скрипты можно выносить в корневой php_interface, но лучше всего — в модули.

В документации можно почитать о порядке выполнения страницы.

Шаблоны компонентов

Правильнее складывать шаблоны компонентов в текущий шаблон сайта. Это своего рода неймспейсы, привносящие ясность о принадлежности шаблона компонента к конкретному сайту. С таким подходом:

  • не возникнет необходимости городить избыточное название шаблона компонента (напр., bitrix:news) для нового сайта (ага, один news уже был кастомизирован для первого сайта);
  • при редизайне сайта нужно просто создать новые шаблоны сайта и компонентов, не затирая старые, не городя названия в стиле «news_v2»;

Шаблоны компонентов, используемые в разных шаблонах сайтов можно размещать в /local/templates/.default/. Для удобства его принадлежность к конкретному проекту я выделяю приставкой в начале названия: (project.template_name).

Сортировка сайтов

Со многими, наверное, был такой случай: создал сайт в «Битриксе», зашёл на него, а показывается другой. Дебажишь константу SITE_ID, а в ней совсем не то. Проверяешь адреса, настройки — всё ОК. Но сайт не определяется. А дело-то всё в порядке сортировки сайтов — субдомены должны иметь индекс сортировки выше, чем основные сайты. И ещё нужно расставлять приоритет в зависимости от названия: у abs.site.ru выше, у qwe.site.ru — ниже. Прямо как в настройках «Апача».

«Адреса сайтов»

Частенько бывает нужно перелинковать сайты друг на друга, типичный пример: site.ru и job.site.ru. Создавать лишние константы — плохо, особенно, когда для этой задачи в «Битриксе» почти всё есть. В настройках сайта через админку можно указать УРЛ сервера и получить эти данные с помощью метода \Bitrix\Main\SiteTable::getList(). Вот только указанный метод обращается напрямую к БД. Решить эту проблему можно с помощью модуля «Адреса сайтов», который хранит информацию в дисковом кеше и имеет удобное АПИ для работы с ней.

И ещё раз о php_interface

Лично меня, когда я был «маленьким битриксоидом», пугали модулями. Мол, там всё непросто, и лучше с ними не связываться. Действительно, там есть свои особенности, если делается решение для «Маркетплейса». Но фактически, модуль — тот же самый компонент, только круче и интереснее.

Модуль быстро собирается, особенно, если делать это из заготовленных шаблонов. В модуле поддерживается автозагрузка классов, есть опции (редактируются через админку) и всё то же самое, что и в каталоге php_interface. Только структурированное.

Есть мнение, что создание модуля должно быть оправдано. Я считаю иначе: должно быть оправдано использование php_interface.

Синхронизируйся!

На мой взгляд, одно из самых полезных достижений веба за последние пару лет — распространение и доступность облачных хранилищ. Все файлы и настройки самостоятельно кочуют от устройства к устройству. Удобно, но всё же не многие жалуют облака.

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

Расскажу о своей «архитектуре», претерпевшей множество изменений за последние пару лет.

«Гугл-диск» использую для работы с документами: рабочими, учебными и личными. У «Гугла» двухфакторная авторизация, неплохая скорость синхронизации и упрощённый аналог офисного пакета «Майкрософта».

«Яндекс-диск» хорошо подходит для котиков, фоточек, музыки и прочих развлекательно-личных файлов. Приятный, продуманный интерфейс, хорошая скорость, автозагрузка фотографий с возможностью их обработки. Несмотря на критическую ошибку, допущенную в прошлом году, сервис достаточно качественный и пребывает в состоянии постоянного совершенствования.

«Облако Мэйл.ру» применяю для хранения бекапов. Как и многие проекты компании, имеет плохую репутацию и неудобный интерфейс. Иногда замечал возникновение конфликтов при «быстром» изменении файлов и папок. Хранить важные незащищённые файлы здесь не рекомендую. Честно говоря, использую это облако только из-за объёма — 1 Тб. Разумеется, на это и сделала ставку «Мэйл.ру».

В «Дропбоксе» размещено портативное ПО, которым я могу пользоваться на любом компьютере. При чём вместе с программами синхронизируются и их настройки.

По долгу службы я использую среду разработки, хранящей массу настроек и информации о проектах. Оказавшись за другим компьютером без этих данных чувствуешь себя как без рук. В решении этой проблемы мне помогает «Гуд-синк». Он умеет синхронизировать любые файлы и каталоги ПК с удалённым сервером. Есть несколько вариантов запуска синхронизации: по расписанию, после изменения файлов, при включении / выключении компьютера и периодически через установленный промежуток времени. Сначала я применял для этих целей «Облако Мэйл.ру», потом «Яндекс-диск», но в обоих сервисах постоянно происходили конфликты из-за быстрого и частого изменения файлов и папок.

Ну и конечно обозреватели. «Хром», «Яндекс-браузер» и «Файрфокс» — все они синхронизируют настройки и приложения.

Облачные технологии просты и удобны, но помните: данные в облаке уже не только ваши данные.

2014  

«Адреса сайтов»

В многосайтовых разработках одного проекта на «Битриксе» периодически возникает необходимость в перелинковке сайтов. Типичные примеры: иноязычные версии сайта; подсайты проектов, дочерних компаний, размещаемые на других доменах. Простое решение — создать константы. Удобное решение — использовать данные из БД, хранящиеся в настройках сайтов. «Битрикс» умеет отдавать эти данные только после непосредственного обращения к БД. Понятное дело, такой расклад неприемлем.

center

Так были созданы «Адреса сайтов» — решение, облегчающее жизнь разработчиков. АПИ модуля умеет отдавать данные о всех сайтах системы, и, при необходимости, генерировать на каждом хите динамические константы. Информация забирается из файлового кеша, обращения к БД происходят только при добавлении нового или обновлении старых сайтов (ну и при устаревании кеша, разумеется).

В зоне Bitrix\Siteurl находится класс Sites, в котором доступны сл. методы:

getUrl();
getName();
getDomain();
getList();

У всех необязательный параметр $siteId по-умолчанию равен идентификатору текущего сайта. Метод getList() имеет второй параметр — $field, позволяющий ограничивать выборку.

use Bitrix\Siteurl;

Bitrix\Main\Loader::includeModule('nik.siteurl');

/**
 * Вернёт массив всех сайтов со всеми полями:
 * [s1] => array(NAME => Сайт 1, DOMAIN => site.ru, URL => http://site.ru)
 * [s2] => array(NAME => Сайт 2, DOMAIN => eng.site.ru, URL => http://eng.site.ru)
 * [s3] => …
 */
Sites::getList();

/**
 * Вернёт массив всех сайтов и поле «Название веб-сайта»:
 * [s1] => Сайт 1
 * [s2] => Сайт 2
 * [s3] => …
 */
Sites::getList(false, 'NAME');

/**
 * Вернёт массив всех полей сайта с идентификатором s2:
 * array(NAME => Сайт 2, DOMAIN => eng.site.ru, URL => http://eng.site.ru)
 */
Sites::getList('s2');

Если в настройках модуля активировать генерацию констант, оные будут создаваться на каждом хите. Данные берутся из кеша. Напр., если в системе заведено два сайта с идентификаторами s1 и it, нам будут доступны константы (всегда заглавными буквами):

S1_NAME
S1_DOMAIN
S1_URL

IT_NAME
IT_DOMAIN
IT_URL

Короче, жизнь теперь станет проще.

Скачать с маркетплейса

«Элементарий». Особенности создания модуля для «1С-Битрикса»

Сегодня в маркетплейсе «Битрикса» появился «Элементарий» — мой пилотный проект. Название модуля отражает его простоту и область применения.

Первая версия показывает в формах редактирования элементов инфоблоков информацию из журнала событий — кто создал, сколько раз, кем и когда был изменён элемент. На случай, если по каким-то причинам вывод данных из журнала событий не подходит, можно использовать второе свойство — «Кто создал / изменил элемент?» Оно базируется на данных таблицы инфоблока.

Публикация решения в маркетплейсе

В целом, механизм публикации довольно-таки удобный. Вы просто заполняете форму в личном кабинете, читаете условия и напоминания. Комментарии от модераторов и клиентов тоже можно читать в ЛК. Однако, ложку дёгтя вносит ограничение поля описания контактов разработчика — не менее 100 символов (рукалицо.джипег).

Не забывайте, что клиенты могут установить ваше решение на старые версии «Битрикса», не имеющие в себе ядра Д7. В установочных файлах применяйте классы только старого ядра.

Модерация

Решения в маркетплейсе тестируются в три этапа.

  1. Автоматически проверяется структура и наличие ключевых переменных.
  2. Модератор устанавливает и проверяет «вменяемость» решения.
  3. Далее, судя по двухнедельным ожиданиям, «битриксоиды» проверяют код.

Подводные камни

Автопроверка ищет в install/index.php строку var $MODULE_ID. Увы, но придётся смириться с пережитком прошлого, объявление через public маркетплейс не примет.

В конструкторе класса установочного файла при подключении version.php используйте функцию include без суффикса _once, иначе информация о модуле не будет подгружаться в разделе «Обновление решений», что вызовет ошибку с кодом Ux11.

Скачать с маркетплейса

Ранее Ctrl + ↓