Своим появлением PHP5 даровал нам такой замечательный инструмент как ленивая подгрузка классов, реализуемая с помощью функции __autoload. К сожалению, Битрикс лишает нас в общем случае использования этой возможности, резервируя её под свои нужды.
Объявление функции __autoload происходит в файле bitrix/modules/main/classes/general/module.php, где функция становится обвёрткой для вызова метода CModule::RequireAutoloadClass($className). Таким образом использовать автозагрузку в Битриксе можно только для классов, подключаемых в рамках модуля. Так что, если Ваш модуль содержит обширное количество классов, рекомендую в файле include.php модуля не подключать классы напрямую через require_once, а воспользоваться методом CModule::AddAutoloadClasses
__autoload — Попытка загрузить неопределенный класс Внимание: Данный функционал объявлен УСТАРЕВШИМ, начиная с PHP 7.2.0 и его использование крайне не рекомендовано.
В данной статье речь пойдёт об использовании механизма транзакций при работе с БД MySQL в Битриксе.
Первым делом стоит сразу отметить, что поддержка транзакций (ровно как и ограничений целостности) в MySQL зависит от выбранного Вами движка БД. Движков этих существует некое множество, но широкое распространение получили два из них: MyISAM и InnoDB. На бескрайних просторах Гугла можно найти бесчисленное количество холиваров на тему, какой же движок лучше и для каких целей. Однако, для нас важно другое - транзакции не поддерживаются в MyISAM, транзакции поддерживаются в InnoDB. Поэтому, если у Вас в качестве движка стоит MyISAM и Вы хотите использовать транзакции, Вам придётся сменить движок с помощью команды ALTER.
Отдельно стоит заметить, что во избежание deadlock'ов в БД, работающей на InnoDB, необходимо отключить устойчивое соединение. В Битриксе это делается это по средствам настройки константы DBPersistent в файле dbconn.php.
Теперь для использования транзакций вместе с API Битрикса остаётся только одна проблема: InnoDB не поддерживает вложенных транзакций (такая поддержка есть на сколько мне известно в Oracle). То есть в результатом запроса
CREATE TABLE a
(
data varchar(255)
) ENGINE=InnoDB;
BEGIN;
INSERT INTO `a` (`data`) VALUES ('a');
BEGIN;
ROLLBACK;
ROLLBACK;
SELECT * FROM `a`;
будет строка с полем `data` равным "a". Это происходит потому, что ввиду отсутствия поддержки механизма вложенных транзакций второй BEGIN автоматически делает COMMIT для предыдущего, тем самым закрывая в случае наличия текущую транзакцию и открывая новую. Ввиду выше описанного возникает в целом неразрешимая проблема. Если в своих модулях (например в модуле iblock) пацанчики из Битрикса начнут использовать транзакции, использование транзакций на уровне API (пример ниже) будет бессмысленно. Однако, анализ исходников Битрикса (grep -ri ) показал, что транзакции в модулях Битрикса не текущий момент не используются.
Перейдём к примеру. Описывать его не буду, так код в целом самодокументирован.
<?php
/**
* Пример использования транзакций
*
* Суть примера заключается в создании двух элементов одного инфоблока.
* В случае, если хотя бы один элемент не может быть создан, происходит
* откат всех изменений.
*/
// Подключение Битрикса
require( $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php' );
CModule::IncludeModule( 'iblock' );
// Настройки
define( 'MY_IBLOCK_ID', 1 );
// Инициализация переменных
$bSuccess = true;
$oIBlockElement = new CIBlockElement();
// Запуск транзакции
$DB->StartTransaction();
try
{
// Добавление первого элемента
$iElementId = $oIBlockElement->Add( array(
'IBLOCK_ID' => MY_IBLOCK_ID,
'NAME' => 'ONE',
) );
if( false === $iElementId )
throw new Exception( $oIBlockElement->LAST_ERROR );
// Добавление второго элемента
$iElementId = $oIBlockElement->Add( array(
'IBLOCK_ID' => MY_IBLOCK_ID,
'NAME' => 'TWO',
) );
if( false === $iElementId )
throw new Exception( $oIBlockElement->LAST_ERROR);
// Сохранение данных
$DB->Commit();
}
// Обработка ошибок
catch( Exception $ex )
{
// Откат изменений
$DB->Rollback();
// Сброс флага успеха
$bSuccess = false;
echo 'An error occurred: ' . $ex->getMessage();
}
Область применения можете додумать сами - это по сути любой момент, где требуется соблюсти атомарность записи: создание заказа, шаги мастера (чисто для примера) и так далее.
На последок, хочу ещё раз подчеркнуть, что так как лично у меня нет гарантий, что в модули Битрикса рано или поздно не начнут использование транзакций, полагаться на транзакции с InnoDB Вам следует на свой страх и риск. В случае, если же Ваша БД поддерживает вложенные транзакции - волноваться не о чем
Отдельно стоит заметить, что во избежание deadlock'ов в БД, работающей на InnoDB, необходимо отключить устойчивое соединение. В Битриксе это делается это по средствам настройки константы DBPersistent в файле dbconn.php.
Объясните пожалуйста, как связано постоянное подключение к БД с блокировками? И какими именно какой тип блокировки?
На счёт deadlock'ов - прошу прощения, походу я погорячился. Просто от многих знакомых приходилось слышать рекомендации не использовать устойчивые соединения с транзакционными БД, ибо это тянет за собой кучу проблем, таких как зависшие процессы в БД. В качестве примера сейчас могу привести разве что этот пост.
Область применения можете додумать сами - это по сути любой момент, где требуется соблюсти атомарность записи: создание заказа, шаги мастера (чисто для примера) и так далее.
На обработчики событий смотрели? Могут подложить сюрприз.
Итак, мы создали заказ (элемент), а на основе его пробуем сделать еще что-то. 2-я запись в БД не получается и идет откат. Если на добавление первой записи было событие, то оно сработает (а почему бы и нет?). Не все так просто.
То же самое с "длительными" операциями.
Сам я тоже долго размышлял на эту тему и пришел к выводу, что если работая чистыми методами АПИ у меня "не проходят" (отпадают и т..д) запросы к БД, то это уже проблема не локального, а всего проекта целиком.
Такой механизм стоит использовать аккуратно, когда вы точно знаете зачем вам.
К сожалению, Битрикс не предоставляет нам инструментов для конфигурирования проекта. В большинстве случаев разработчик решает проблему конфигурации проекта, помещая кучу констант в файл php_interface/init.php. Однако, в случае когда проект перерастает некоторую критическую массу, такой подход становится довольно неудобным.
Путей решения тут может быть множество (PEAR::Config для INI/XML/..., Symfony YAML для YAML). Однако, все эти решения относительно "тяжелы".
Я хочу предложить на Ваш суд небольшой класс для создания конфигурации на основе INI-файлов. Сразу скажу, что основная "соль" класса заключается в php-функции parse_ini_file.
/**
* Класс конфигуратора
*
* Класс предназначен для доступа к конфигурации проекта,
* хранящейся в формате INI
*/
class CSlConfig implements ArrayAccess
{
/**
* Ссылка на экземпляр класса
* @var object
*/
private static $_oInstance;
/**
* Путь к файлу конфигурации
* @var string
*/
private static $_sPathToConfig;
/**
* Конфигурация проекта
* @var array
*/
private $_aConfig = array();
/**
* Конструктор
*
* @throws INVALID_CONFIG_FILE
* @return CSlConfig
*/
private function __construct()
{
if( !empty( self::$_sPathToConfig ) && file_exists( self::$_sPathToConfig ) )
$this->_aConfig = parse_ini_file( self::$_sPathToConfig, true );
else
throw new Exception( 'INVALID_CONFIG_FILE' );
}
/**
* Получение экземпляра класса
*
* @return CSlConfig
*/
public static function GetInstance()
{
if( null === self::$_oInstance )
self::$_oInstance = new self();
return self::$_oInstance;
}
/**
* Инициализация конфигуратора
*
* @param string $sFileName Файл конфигурации
* @throws INVALID_CONFIG_FILE
* @return CSlConfig
*/
public static function SetUp( $sFileName )
{
if( empty( self::$_sPathToConfig ) )
self::$_sPathToConfig = $sFileName;
else
throw new Exception( 'CONFIG_FILE_CANT_BE_REDECLARED' );
}
/**
* Установка элемента массива
*
* @param integer $iOffset Смещение элемента
* @param mixed $mValue Значение элемента
* @throws CONFIG_CANT_BE_CHANGED
*/
public function OffsetSet( $iOffset, $mValue )
{
throw new Exception( 'CONFIG_CANT_BE_CHANGED' );
}
/**
* Проверка существования элемента массива
*
* @param integer $iOffset Смещение элемента
* @return bool
*/
public function OffsetExists( $iOffset )
{
return isset( $this->_aConfig[ $iOffset ] );
}
/**
* Удаление элемента массива
*
* @param integer $iOffset Смещение элемента
*/
public function OffsetUnset( $iOffset )
{
unset( $this->_aConfig[ $iOffset ] );
}
/**
* Получение элемента массива
*
* @param integer $iOffset Смещение элемента
* @return mixed
*/
public function OffsetGet( $iOffset )
{
return isset( $this->_aConfig[ $iOffset ] ) ?
$this->_aConfig[ $iOffset ] : null;
}
} // Конец класса CSlConfig
С помощью этого класса работа с INI-файлом
; This is a sample configuration file
; Comments start with ';', as in php.ini
[first_section]
one = 1
five = 5
animal = BIRD
[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"
[third_section]
phpversion[] = "5.0"
phpversion[] = "5.1"
phpversion[] = "5.2"
phpversion[] = "5.3"
будет выглядеть следующим образом:
// Подключение класса
require_once( dirname( __FILE__ ) . '/config.php' );
// Настройка конфигуратора (это будет где-нибудь в php_interface/init.php)
CSlConfig::SetUp( 'config.ini' );
// Работа с конфигом (это будет в любом месте нашего кода)
$oConfig = CSlConfig::GetInstance();
var_dump( $oConfig['first_section'] );
var_dump( $oConfig['third_section']['phpversion'] );
Не когда не понимал почему в пхп пытаются придумать замену конфигурационным массивам их подобием в виде *.ini, хотя последний 1 в 1 является тем же самым массивом, только приходится дополнительно тужится чтоб его можно использовать как массив.
Вы хоть про запрещение на просмотр этого ini через htaccess упомините.
Вы хоть про запрещение на просмотр этого ini через htaccess упомините
Я надеюсь, что это и так всем понятно Хотя я бы рекомендовал, в обще не хранить настройки в DocumentRoot'е Вашего проекта. Например, можно использовать такую структуру папок (/var/www/you.project.com): config - здесь живут конфиги и т.д. htdocs - здесь живёт Битрегз, это DocumentRoot script - здесь живут скрипты (например кроновские)
Не пробывали замерять скорость парсинга большого INI-файла и просто подключения эквивалентного init.php с конфигурационным массивом и набором дефайнов внутри? или лучше время генерации страницы при использовании INI-файла VS. init.php в студию...
Недавно наткнулся на интересную статью об оптимизации скорости загрузки страниц. Вкратце суть предложенного метода состоит в том, чтобы в теге <head> сначала располагались CSS, а только потом JS. Вызвано это тем, что браузер производит загрузку CSS асинхронно, в отличие от JS.
Теперь о том, как реализовать это в Битриксе. Прежде всего мы должны воспользоваться отложенными функциями, для того, что бы вынести все подключения CSS и JS из кода страниц / шаблонов компонентов в тег <head>. В документации мне удалось найти всего одну отложенную функцию, подходящую для этого - CMain::AddHeadString/CMain::ShowHeadStrings. Однако нам в нашем случае понадобится как минимум две. Не много порывшись в исходниках мне удалось познакомиться с функцией CMain::AddHeadScript/CMain::ShowHeadScripts, созданной специально для подключения скриптов.
Итак, решение найдено. Теперь на остаётся заменить прямые подключения CSS на CMain::AddHeadSting и JS на CMain::AddHeadScript в коде:
Что было бы, если бы при приеме на работу к водителям относились так же, как к программистам:
Вакансия: водитель.
Требования: профессиональные навыки управлении легковыми и грузовыми автомобилями, троллейбусами, трамваями, поездами метрополитена и фуникулера, экскаваторами и бульдозерами, спецмашинами на гусеничном ходу, боевыми машинами пехоты и современными легкими/средними танками, находящимися на вооружении стран СНГ и НАТО.
Навыки раллийского и экстремального вождения - обязательны, опыт управления болидами F1 - приветствуется. Знания и опыт ремонта поршневых и роторных двигателей, автоматических и ручных трансмиссий, систем зажигания, бортовых компьютеров, антиблокировочных систем, навигационных систем (GPS) и автомобильных аудиосистем ведущих производителей - обязательны. Опыт проведения кузовных и окрасочных работ приветствуется.
Претенденты должны иметь сертификаты Mercedes, BMW, General Motors, а также справки об участии в крупных международных ралли не более чем двухлетней давности. Зарплата 1500-2500 руб., определяется по результатам собеседования
Хороший врач -- это человек с 5-6 годами обучения, ординатурой и 10-15 годами клинической практики. Хороший программист -- это студент с 2-3 годами опыта разработки. Дорогие программисты, вы себе безбожно льстите, сравнивая себя с врачами.
Терапевт. Это не врач, это менеджер. Он понятия не имеет, как вас лечить, но может сказать, кто это знает. Если знает, кто это знает. Но не факт, что тот, кого он знает, знает, как вас лечить. В общем, несмотря на то, что медицина шагнула далеко вперед, надежда остается по прежнему только на бога, которого, как известно, отменили еще в 1917 году.
Хирург. Хирург он как сапер. Ошибается только один раз. Правда если сапер ошибается только один раз в своей жизни, то хирург ошибается только один раз в вашей жизни. Даже если после ошибки хирурга вам удалось сохранить жизнь, поверьте, она такая вам на хрен не нужна. Как и сапер, хирург руководствуется не накопленной информацией, а интуицией. И в этом наше счастье, поскольку в медицине интуиция по-прежнему куда надежнее.
Оториноларинголог. У этих врачей явный комплекс неполноценности. Сначала их называли ухогорлоносами. Но это им показалось несерьезным. Тогда их стали называть ЛОР-врачами. Но и этого им показалось мало. Теперь они объединились с логопедами, поскольку без помощи логопедов люди произносить их новое название не могут. Да и, честно говоря, не очень-то и хотят. Наиболее существенная помощь от этих врачей, это когда вы, наконец, без слухового аппарата сможете с первого раза расслышать название его профессии. Оно вам надо?
Стоматолог. Иногда, чтобы их сразу не распознали, они называют себя дантистами. Самые страшные врачи. Одно счастье, количество общений с ними у среднестатистического человека ограничено 32 визитами. А для тех, у кого нет зубов мудрости – 28 визитами. А ведь умные люди всегда говорили, что дуракам живется намного легче (на 12,5%). Так что решайте сами.
Окулист. Этим тоже показалось мало и они стали называть себя офтальмологами. Люди крайне неприятные, поскольку всегда хотят, чтобы вы видели то, на что глаза бы ваши не смотрели.
Гинеколог. Самые обделенные врачи, поскольку у них в два раза меньше пациентов, чем у остальных эскулапов. Интересно, что среди гинекологов практически не встречаются мужчины. Поскольку в гинекологии все строго – либо ты мужчина, либо гинеколог. Попробуйте 61320 часов в год смотреть на самые интересные части тела женщин, и гарантирую вам, вы быстро потеряете к ним интерес. Нельзя превращать хобби в профессию.
Акушер. Самый уважаемый в медицине врач. Именно он обеспечивает работой всех остальных врачей.
Венеролог. Единственный врач, встреча с которым сопряжена хоть с чем-то приятным. Да уж... Например, с приятными воспоминаниями. Это самый честный врач. Он – единственный, кому вы платите за удовольствие, даже несмотря на то, что это удовольствие доставил вам не он.
Невролог. Теоретически может вылечить все, кроме разве сифилиса и переломов, поскольку все болезни от нервов. Практически же абсолютно бесполезен. Он может вам сказать «Не нервничайте», но так же как и вы понятие не имеет, как этого добиться.
Аллерголог. Самый проактивный врач. Он абсолютно уверен (и надо отметить, у него есть на то основания), что все жители этой планеты являются его пациентами. Поэтому главная цель в жизни аллерголога – это найти у вас аллергию, пока вы от него не сбежали.
Психиатр. А это, соответственно, самый пропассивный врач. В отличие от аллерголога, он только смутно догадывается, что все жители этой планеты являются его пациентами, и не хочет посмотреть правде в лицо. Пользы от него тоже немного. Ну скажите, разве может больному помочь другой больной? Интересно, что психотерапевты существуют, а вот психохирурги так и не появились.
Реаниматолог. Самый завистливый врач. Он просто не может допустить, чтобы вы были счастливы в то время, пока он вынужден оставаться в этом дерьмовом мире.
Нарколог. Нет, вру. Вот они точно самые завистливые, поскольку хотят лишить человека последней радости в жизни.
Сексопатолог. Дай бог вам так никогда и не узнать о его существовании.
Сексолог. Это светлая сторона сексопатолога. Сексопатолог говорит вам о том, что у вас плохо. Сексолог говорит о том, как вам сделать это еще лучше. Вечная тема – борьба света и беспросветности.
Дерматолог. Зря смеетесь. При всей неблагозвучности – очень нужный, хотя и очень несчастный врач. Вам интересно, кто живет у вас под ободком унитаза и в других труднодоступных местах? Нет? А он каждого этого гада должен знать в лицо!
Проктолог. Несмотря на то, что медицина шагнула далеко вперед, эти врачи как были, так и остались в заднице.
Анестезиолог. Очень полезный врач. Он делает так, чтобы вы ничего не почувствовали. А если он ошибется – это даже к лучшему. В этом случае вы уже больше ничего не будете чувствовать.
Гастроэнтеролог и диетолог. Абсолютно бесполезный продукт прогресса. До середины XX века их вполне успешно заменяли Соловки, Воркута, Сахалин и другие места естественного лечения.
Иммунолог. Самый ленивый врач. Он всегда пытается переложить свою работу на ваш организм.
Пульмонолог. Единственный врач, который не разделяет заблуждение своих коллег, что если бросить курить, все болезни пройдут сами собой.
Уролог. Врач с очень узким кругозором. В отличие от сексопатолога и сексолога рассматривает ваше мужское достоинство исключительно с точки зрения его побочных функций.
Кардиолог. Абсолютно лишен романтических чувств. Только у него слова «Сердце, тебе не хочется покоя» не вызывают никаких положительных эмоций.
Травматолог. Эти врачи очень любят спорт. Практически всего его виды, за исключением разве шахмат.
Фармаколог. Если большинство врачей занимаются тем, чтобы удалить из организма лишнее, то фармакологии наоборот пытаются запихнуть в него всего и побольше. И с интересом потом наблюдают, каким образом организм будет реагировать на издевательства над собой.
Токсиколог. Благодаря фармакологам этот врач никогда не останется без работы. По крайней мере, на текущий момент фармакологии обеспечивают его работой более чем на 50%.
Вирусолог. Очень общительный врач. Именно ему выпало на долю редкое счастье практически ежедневно расширять круг своего общения.
Эпидемиолог. Тот же вирусолог, но страдающий манией величия.
Педиатр. Очень жестокие люди. Если все остальные врачи достают нас уже в сознательном возрасте, то педиатры готовы лишить нас самых прекрасных дней нашей жизни – нашего детства.
Ортопед. Устраняет последствия издевательств человека над собственным организмом. Если педиатр начинает интересоваться нами с момента рождения, то в руки к ортопеду мы обычно попадаем сразу после поступления в школу. В этом плане ортопеды тесно сотрудничают с министерством образования.
Ревматолог. Самый безобидный врач. Обычно он приходит к вам, когда с вас уже песок сыпется и вам уже безразличны последствия его лечения.
Рентгенолог. Эти врачи отлично устроились. Сначала они изучают вас рентгеновскими лучами. Потом изучают негативные последствия своего предыдущего изучения. Рентгенолог в принципе может узнать о вас много интересного, если у него вдруг неожиданно появится желание воспользоваться плодами своего труда.
Сомнолог. Что, никогда не слышали? А зря. Эти врачи готовы покуситься на самое святое, что у нас есть – на сон. Чисто теоретические – очень полезная и даже универсальная отрасль медицины. Только сомнологи додумались, что порою достаточно вылечить одного человека от храпа, чтобы спасти от бессонницы всех, кто его окружает. Но вот как вылечить этого одного, они додуматься еще не успели.
Физиотерапевт. По-моему это просто садист. Он почему-то уверен, что если вас хорошенько шарахнуть током, то вам станет намного легче. Видимо в детстве эти врачи любили совать пальцы в розетку, и теперь считают, что и все остальные должны пройти через мучения, которые когда-то испытали они.
Эметолог. А вы думали это все так просто — с вечера нажрались и ну всю ночь обнимать унитаз. А вот и нет. Эметолог с научной точки зрения точно знает, от чего вас тошнит. Даже если ваш тошнит от него самого.
Эндоскопист. Этого медом не корми, дай потыкать в вас всякой хренью, назначение которой порой неизвестно ему самому. Впрочем, метод вполне действенен. Организм очень часто вместе с эндоскопом сам извергает из себя все то, что эндоскопист из него и пытался получить.
Судмедэксперт. Единственный врач, который даже не пытается сделать вид, что он кого-то лечит.
Патологоанатом. Самый высокопрофессиональный из всех врачей. Только он точно знает, что и отчего у вас болело.
Герои замечательного буржуйского сериала "IT Corwd" на все вопросы пользователей отвечали "а Вы пробовали выключить и влючить снова?". Техподдержка Битрикса, должен признать, в целом работает лучше, однако их ответы порой меня убивают:
Время: 28.05.2009 19:14:09 От кого: [38339] (vlad.bx) Vladislav Levada
Добрый день!
Спасибо за ваше сообщение. Мы сообщим о данных проблемах разработчикам для исправления в новых версиях продукта.
Ни сроков выполнения, ни что самое важное версии, в которой баг будет исправлен, саппорт Битрикса не сообщает никогда - лучшее на что можно надеяться, это инструкция с указанием, что и где нужно залатать, что бы их чудо-система заработала.
Конечно, если б это был опенсурс продукт, я бы сам с радостью в свободное от работы время нашёл ошибку, придумал бы путь решения, отписался бы им, и гордый тем, что сделал что-то хорошее, пошёл пить пиво. Но такой подход к клиентам коммерческой организации меня немного удручает.
P.S. Я не перестаю удивляться гениальности манагеров Битрикса: выпустить довольно херовенький продукт, разрекламировать его так, что-бы менеджеры писали при виде его кипятком, а качестве тестировщиков использовать программистов тех компаний, которым удалось впендюрить (при чём за деньги) этот продукт. Ребята, браво!
Не стоит удивлятся. Помню как-то на инет-магазе настраивал я оплату картами через assist. Сам assist немного изменил у себя формат ответа сервера из-за чего битрикс перестал правильно его обрабатывать. Нашел я эту ошибку, написал техподдержке как ее исправить, мне пообещали включить это в ближайшие версии, а когда также не сказали. В итоге, в апдейтах так и не пришло исправление данного обработчика. Сейчас может уже и поправили. В целом продукт неплохой, но конечно бывают ситуации когда надо ковырять исходники, но я заметил тенденцию, что я это делаю теперь все реже и реже.
Не согласен так уж категорично.. херовеньким его теперь уже не назовешь. Функционал мощный. Есть неприятные моменты, но только в компонентах. Это у ребят больное место. Они категорически не хотят их делать хорошими.
Признаю, погорячился - эмоции . API отностительно других CMS, предоставляющих коробочные решения, в целом неплохое - местами даже удачное, но общая картина меня всё равно удручает.
При разработке сколь-либо серьёзных проектов зачастую просто необходимо использовать систему контроля версий, например SVN. К сожалению, Битрикс не позволяет вести командную разработку на нескольких локальных машинах, ввиду особенностей его лицензий. Тем не менее, система контроля версий может быть использована в паре с Битрикс в качестве хранилища бэкапов.
Однако, внесение проекта на Битрикс под контроль SVN, не совсем тривиальная задача. Как минимум излишнем будет хранить файлы ядра Битрикса, так как: 1. Они не имеют никакого отношения к проекту 2. Их слишком много 3. Они постоянно обновляются
Казалось бы ничего страшного - ставим svn:ignore на папку bitrix и радуемся жизни. Но в таком случае мы не внесём под контроль SVN свои компоненты, шаблоны, настройки. Для решения этой проблемы я предлагаю воспользоваться механизмом символьных ссылок.
И так, суть решения состоит в следующем. Допустим Ваш проект располагается в каталоге /var/www/project и имеет следующую структуру папок: * etc - каталог настроек * bin - каталог вспомогательных скриптов * lib - библиотеки * www - document root сайта
Теперь действуем по пунктам: 1. Добавляем пустое дерево каталогов /var/www/project под контроль SVN 2. Разворачиваем Битрикс в /var/www/project/www 3. Проставляем свойство ignore для каталога www (svn propedit:ignore www), указывая в нём каталоги bitrix и upload 4. Коммитим (svn commit), обновляем (svn update) SVN - теперь она не обращает внимание на файлы в папках www/bitrix и www/upload 5. Переносим содержимое каталога www/bitrix/php_interface в каталог etc 6. Удаляем каталог www/bitrix/php_interface 7. Создаём символическую ссылку (находясь в каталоге www/bitrix выполняем ln -s ../../etc php_interface) 8. Пункты 5-7 повторяем для своего пространства имён компонентов, шаблонов и модулей (их можно положить в lib/componets, lib/templates и lib/modules соответственно).
После этого добавляем под контроль SVN все, видимые ей файлы в текущем репозитории и радуемся жизни.
P.S. Структуру tag/branch/trunk не стал организовывать для упрощения примера.
Честно говоря, до сегодняшнего дня считал, что Windows не поддерживает символических ссылок, однако, (Википедия) сейчас убедила меня в обратном:
Для каталогов в файловой системе NTFS, начиная с Windows 2000, существует поддержка символьной ссылки, путем команды linkd (Microsoft Windows Resource Kit). А начиная с Windows Vista — команда mklink
Так что есть вероятность, что вышеописанный манёвр можно портировать и на Windows.
При работе в режиме докуметооборота элемент инфоблока (в смысле полноценной единицы, доступной через стандартные методы API - например CIBlockElement::GetByID) не создаётся до тех пор, пока в рамках докуметооборота он не достигнет финального статуса "Опубликован", либо любого другого статуса с поднятым флагом IS_FINAL (этот флаг нельзя выставить через админку Битрикса, только правкой БД).
Естественно, что до этого момента записи в инфоблок заноситься будут, однако для стандартных методов API с параметрами по умолчанию они будут не доступны. Основным отличием "промежуточных" элементов от "конечных" является поле "WF_PARENT_ELEMENT_ID", которое пусто для "конечных" элементов и содержит идентификатор "конечного" элемента для промежуточных элементов. В случае создания нового элемента в документообороте (при условии, что начальный статус документооборота не является финальным) будет создан элемент, в поле "WF_PARENT_ELEMENT_ID" будет записан его собственный идентификатор. При последующем переводе элемента в любой другой статус документооборота, в том числе и в финальный, в инфоблоке будут создаваться новые элементы с полем "WF_PARENT_ELEMENT_ID". И наконец при переводе элемента в финальный статус элемнт, с которого всё началось, будет обновлён так, что поле "WF_PARENT_ELEMENT_ID" станет пустым, а поле "WF_STATUS_ID" станет равным значению финального статуса (зачастую это 1). При последующем переводе элемента в какой-либо промежуточный статус круг повториться с той небольшой разницей, что в качестве отправной точки будет использоваться текущий опубликованный элемент.
По умолчанию API позволяет нам работать только с опубликованными элементами. Причём если перевести опубликованный элемент в какой либо другой статус, то API будет возвращать именно ту версию элемента, которая соответствует опубликованной. Для того, что бы получить список всех элементов (в том числе и не опубликованных) у метода CIBlockElement::GetList в свойствах фильтра необходимо задать параметр "SHOW_HISTORY" => "Y". Кроме того, существует возможность (почему-то недокументированная) зная "ID" элемента получить его последнюю версию в документообороте с помощью функции CIBlockElement::WF_GetLast(), и наоборот - зная последнюю версию элемента получить его оригинальный "ID" с помощью функции CIBlockElement::GetRealElement().
Отдельно стоит упомянуть обработчики событий в целом и OnAfterIBlockElementUpdate в частности. Так как в случае работы с документооборотом непосредственный Update происходит только в случае перевода элемента в финальный статус, не следует ожидать вызова обработчиков этого события при переводе элемента в "промежуточные" статусы. В место этого, как видно из выше сказанного, стоит добавить обработчик на событие OnAfterIBlockElementAdd и ориентироваться на поля "WF" == "Y" (признак того, что элемент участвует в документообороте) и "WF_PARENT_ELEMENT_ID" (идентификатор "конечного" элемента).
На последок замечу, что выше сказанное получено дедуктивным путём и может быть не совсем верно
Спасибо просвятил!! а как вытащить кол-во элементов без многократного обращения к методам, просто и изящно не нагружая систему? ведь мне просто надо кол-во элементов(всех) а не только опубликованных.
а как вот к примеру узнать где какая таблица и как они взаимосвязаны? ответьте плс)) а то на проекте записей под 200000 через апи всё криво и тормозит на выделенной тачке, ух какая жесть
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».