PHP Fatal error: ob_end_clean(): Cannot use output buffering in output buffering display handlers in /home/bitrix/ext_www/_____________/bitrix/modules/main/classes/general/main.php on line 3113
SEL ECT `ID`, `IBLOCK_ID`, `NAME` FR OM `b_iblock_element`
WHERE `ID` IN (115, 120, 117, 109, 128) AND `IBLOCK_ID` = 5
ORDER BY FIELD(`ID`, 115, 120, 117, 109, 128);
Успешно запустил свой домашний блог, написанный на bitrix, на версии php7. Версия bitrix – последняя beta. Замерил утилитой ab-тестирования (из комплекта с Апатчем) скорость работы в первом и втором случаях:
Методика тестирования: Меняем версию PHP в настройках апатча и прогоняем тесты ab-утилитой. Также смотрим на время генерации страницы модулем производительности. Ничего особенно, но для ответа на вопрос: а быстрее ли bitrix с php7? и примерно на сколько быстрее?
Usage: ab [options] [http://]hostname[:port]/path
Options are:
-n requests Number of requests to perform
-c concurrency Number of multiple requests to make at a time
-s timeout Seconds to max. wait for each response
Default is 30 seconds
-k Use HTTP KeepAlive feature
…
Результаты следующие:
PHP 5.6 on Bitrix Vs.
PHP7 (Zend Engine v3.0.0) on Bitrix
Apache/2.4.20 (Win64) PHP/5.6.20
Document Length: 2987 bytes
Concurrency Level: 10
Time taken for tests: 134.852 seconds
Complete requests: 5000
Failed requests: 2
Requests per second: 37.08 [#/sec]
Time per request: 269.703 [ms]
Time per request: 26.970 [ms] (mean, across all concurrent requests)
Transfer rate: 130.68 [Kbytes/sec] received
Apache/2.4.20 (Win64) PHP/7.0.5
Document Length: 2987 bytes
Concurrency Level: 10
Time taken for tests: 130.592 seconds
Complete requests: 5000
Failed requests: 2
Requests per second: 38.29 [#/sec]
Time per request: 261.183 [ms]
Time per request: 26.118 [ms] (mean, across all concurrent requests)
Transfer rate: 133.86 [Kbytes/sec] received
Percentage of the requests served within a certain time (ms)
50% 98
66% 104
75% 108
80% 111
90% 120
95% 131
98% 151
99% 215
100% 42081 (longest request)
Percentage of the requests served within a certain time (ms)
50% 77
66% 83
75% 88
80% 91
90% 105
95% 123
98% 148
99% 187
100% 42048 (longest request)
Как видно, местами процентов на 40% быстрее. Что интересно, что и скорость отдачи контента сервером увеличилась (см. transfer rate). Как мне кажется, это хороший показатель.
PS\2 в момент запуска php7 столкнулся со следующей ошибкой компонента:
Лечится более четким указанием определяемого значения переменной через {}:
// \bitrix\components\bitrix\blog.blog\component.php
global ${$arParams["FILTER_NAME"]};
$arFilter = ${$arParams["FILTER_NAME"]}; // вот так мы явно указываем имя переменной
if(!is_array($arFilter))
$arFilter = array();
PS Выходит очень круто, что просто обновляя версию php, получаем прирост! Очень радует, что битрикс понимает важность перехода на php7, и что уже даже что-то работает
В статье будут рассмотрены темы: — Развитие синтаксиса PHP — Будет дан ответ на аксиому "почему только 5.3, не выше?" и что из нового синтаксиса можно. — Вопрос совместимости, "исторические хвосты"
Мы в данный момент работаем по версии 5.3. Ниже я описываю новые улучшения в 5.4 и 5.5. К сожалению, возможности из этих версий пока использовать НЕЛЬЗЯ. Можно использовать только возможности 5.3.
Важно! Пиши на PHP 5.3! Все вещи, которые доступны выше 5.3 необходимо решать путем создания промежуточных вспомогательных переменных!
Итак, чтобы рассмотреть эту аксиому подробнее, рассмотрим эволюцию синтаксиса PHP, что же появилось в новых версиях (будут рассмотрены не все улучшения, а только вопросы коротких разыменований, и важных в связи с выходом D7).
2/ Имеем еще одну защиту нашего апатча от DDoS-атак.
Интересно было бы, если кто-то еще поделился своим опытом использования модуля, в принципе, при наличии прямых рук легко прикручивается к апатчу на bitrix VM.
Либо может еще есть удобные какие-то способы у вас.
[для врезки вправо]
На последок для выявления перегруза слотов апатча, команды через SSH:
ddos в идеале отлавливать до хостера... в случае похуже – на хостере... в еще более худшем случае – до nginx/apache... Но отлавливать на апаче – это, извините, стыд... Хотя, если атака слабенькая, то пост имеет место быть.
Я думаю, что периодически многие сталкиваются с отладкой ошибки, возникающей при перекодировке ваших модулей в маркеплейсе в демо-режим. Некоторый функционал по сперва непонятным причинам отваливается.
Делюсь найденными наблюдениями, а также как это можно избежать и учесть.
Оказывается, нельзя использовать одноименные параметры функций и переменные-члены классов внутри. вот пример обработчика из файла include.php реального модуля :
public function OnBuildGlobalMenu(&$aGlobalMenu, &$aModuleMenu)
{
/* @var $adminMenu \CAdminMenu */
global $adminMenu;
if (! is_array($adminMenu->aGlobalMenu)) {
return;
}
битрикс кодировщик превращает данный код в файле include.php для демо-версии в подобное:
public function OnBuildGlobalMenu(&$_319480480, &$_678570816)
{
global $adminMenu;
if (!is_array($adminMenu->_319480480)) {
return;
}
естественно, поля класса $adminMenu->_319480480 просто нет, и событие не работает.
поэтому следует избегать совпадение имен параметров и используемых полей объектов внутри методов, дабы избежать подобной коллизии (по крайней мере в кодируемых для демо-режима файлах include.php и install.php).
PS возможно, это пофиксят в кодировщике, это было бы предпочтительнее.
С версии 7.2.2 битрикс-машины появилась возможность подключать бесплатные валидные SSl-сертификаты от Lets Encrypt прямо из меню виртуальной машины.
Let’s Encrypt — центр сертификации, начавший работу в бета-режиме с 3 декабря 2015 года, предоставляющий бесплатные криптографические сертификаты для HTTPS. Процесс выдачи сертификатов полностью автоматизирован. Сертификаты выдаются только на 3 месяца для предотвращения инцидентов безопасности.
Первая попытка установить сертификат прошла с отладкой и выяснениями.
Нам при работе с построителем запросов Bitrix\Main\Entity\Query не хватает:
1/ Мануал по использованию метода registerRuntimeField(), в частности по настройке типов полей $fieldInfo 2/ Примеры решения типичных задач через построитель запросов 3/ можно ли получить сформированный SQL в построителе запросов без предварительного исполнения запроса?
Делюсь недавней находкой, как решить следующую задачу:
Необходимо выбрать из таблицы элементов инфоблока 1.0 элементы, отсортированные по значению свойства, заданного кодом.
Решение будет следующим, выбираем из таблицы b_iblock_element элементы инфоблока, а также к таблице джойним таблицу b_iblock_element_property со всеми свойствами, однако фильтруем именно нужное нам с кодом 30:
// дамп запроса на быструю руку
$showLastQuery = function ($queryBuilder) {
echo '<h4>' . wordwrap($queryBuilder->getLastQuery(), 150) . "</h4>\n\n";
};
// инфоблок 1.0. Выбираем элемент и одно свойство, по нему делаем сортировку.
// алиас поля делаем DOC_ID
use Bitrix\Iblock as ib;
use Bitrix\Main as bm;
$propertySelectAndSortId = 30;
$propertyFieldName = 'DOC_ID';
$queryBuilder = new bm\Entity\Query( ib\ElementTable::getEntity() );
$elC = $queryBuilder
->setSelect( array('NAME', 'ID', 'IBLOCK_ID', $propertyFieldName) )
->registerRuntimeField($propertyFieldName, array(
"data_type" => '\Bitrix\Iblock\ElementPropertyTable',
'reference' => array('=this.ID' => 'ref.IBLOCK_ELEMENT_ID'),
))
->setFilter(array(
'IBLOCK_ID' => 10,
'IBLOCK_ELEMENT_' . $propertyFieldName . '_IBLOCK_PROPERTY_ID'
=> $propertySelectAndSortId
))
->setOrder( array('IBLOCK_ELEMENT_' . $propertyFieldName . '_VALUE' => 'ASC') )
->exec()->fetchAll();
$showLastQuery( $queryBuilder );
echo count($elC);
xdebug_var_dump($elC);
Итого мы получаем следующую картинку:
дамп итогового запроса:
SEL ECT
`iblock_element`.`NAME` AS `NAME`,
`iblock_element`.`ID` AS `ID`,
`iblock_element`.`IBLOCK_ID` AS `IBLOCK_ID`,
`iblock_element_doc_id`.`ID` AS `IBLOCK_ELEMENT_DOC_ID_ID`,
`iblock_element_doc_id`.`IBLOCK_PROPERTY_ID` AS `IBLOCK_ELEMENT_DOC_ID_IBLOCK_PROPERTY_ID`,
`iblock_element_doc_id`.`IBLOCK_ELEMENT_ID` AS `IBLOCK_ELEMENT_DOC_ID_IBLOCK_ELEMENT_ID`,
`iblock_element_doc_id`.`VALUE` AS `IBLOCK_ELEMENT_DOC_ID_VALUE`,
`iblock_element_doc_id`.`VALUE_TYPE` AS `IBLOCK_ELEMENT_DOC_ID_VALUE_TYPE`,
`iblock_element_doc_id`.`VALUE_ENUM` AS `IBLOCK_ELEMENT_DOC_ID_VALUE_ENUM`,
`iblock_element_doc_id`.`VALUE_NUM` AS `IBLOCK_ELEMENT_DOC_ID_VALUE_NUM`,
`iblock_element_doc_id`.`DESCRIPTION` AS `IBLOCK_ELEMENT_DOC_ID_DESCRIPTION`
FR OM `b_iblock_element` `iblock_element`
LEFT JOIN `b_iblock_element_property` `iblock_element_doc_id` ON `iblock_element`.`ID` = `iblock_element_doc_id`.`IBLOCK_ELEMENT_ID`
WHERE `iblock_element`.`IBLOCK_ID` = 10
AND `iblock_element_doc_id`.`IBLOCK_PROPERTY_ID` = 30
ORDER BY `iblock_element_doc_id`.`VALUE` ASC
дамп одного элемента итерации, как видите все поля таблицы свойств b_iblock_element_property заджойнились, но мы выбрали только нужное нам свойство и успешно по нему выполнили сортировку:
Также мы добавили следующее событие, чтобы не дописывать в урле orm=y для запуска генератора запросов:
/bitrix/php_interface/include/lib/handlers.php:
AddEventHandler('main', 'OnBeforeProlog', function () {
global $APPLICATION;
if ($APPLICATION->GetCurPage() == '/bitrix/admin/perfmon_tables.php' && $_GET['orm'] != 'y') {
LocalRedirect( $APPLICATION->GetCurPageParam("orm=y") );
}
});
Итог:
1/ Хотим документацию по построителю запросов, а еще больше по примерам решаемых задач. 2/ Очень хотим \Bitrix\Iblock\ElementPropertyTable и прочие сущности из коробки, которые часто используются в проектах 3/ Хотим диаграмму классов по D7!
Pogudin Sergey, для использования d7 нужно создать класс для работы с таблицой со значениями свойств (используется для создания класса orm-генератор в модуле производительности).
Видимо в новых обновлениях удалили файл bitrix\modules\iblock\lib\elementproperty.php
Pogudin Sergey, переводите в отдельные таблицы. У вас появятся отдельные таблицы b_iblock_property_sN и b_iblock_property_mN, где N - ID инфоблока. Далее идете http://yoursite.domain/bitrix/admin/p...g=ru&orm=y параметр orm=y обязателен, щелкаете правой клавишей мышки и выбираете ORM. Битрикс выдаст вам уже готовый шаблон класса для выбранной таблицы
Чтобы избавиться от PROPERTY_N в запросах. Рекомендую сразу прописать алиасы полей, например:
'MY_PROPERTY_SYMBOL_CODE' => array(
'data_type' => 'float',
'column_name' => 'PROPERTY_203', // реальное имя поля в БД
'title' => Loc::getMessage('ELEMENT_PROP_S46_ENTITY_PROPERTY_203_FIELD'),
),
далее в селектах будете уже использовать MY_PROPERTY_SYMBOL_CODE, оно кстати может и не совпадать с заданным в свойствах инфоблока.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».