Ответы пользователя по тегу PHP
  • Как организовать масштабирование/отказоустойчивость интернет-магазина?

    smilingcheater
    @smilingcheater
    Если без значительного переписывания кода:
    Вынести БД на отдельный сервер. При росте нагрузки - добавлять сервера и настраивать репликацию между ними.
    Сделать отдельный балансировщик - сервер, на который приходят запросы, и который раскидывает их на разные сервера, выполняющие код. При увеличении нагрузки - увеличивать число нод, выполняющих код. Если одна из нод по какой-то причине перестаёт отвечать - остальные продолжают работать.
    Если у вас сессии хранятся в файлах - придётся переносить их хранение в базу/Redis/...
    Ответ написан
  • Почему при загрузке проекта через Composer вылезает Class 'GuzzleHttp\Client' not found?

    smilingcheater
    @smilingcheater
    Когда вы создаёте новый инстанс скраппера
    $instagram = new \InstagramScraper\Instagram(new \GuzzleHttp\Client());

    вы ему на вход передаёте new \GuzzleHttp\Client, но сам этот пакет у вас не установлен (судя по надписи на скрине ./composer.json has been created у вас вообще больше ничего не установлено). Установите и его тоже.
    composer require guzzlehttp/guzzle
    А вообще - ошибка элементарная, учитесь внимательно читать и гуглить.
    Ответ написан
  • Как найти ошибку в коде PHP?

    smilingcheater
    @smilingcheater
    <a href="<?= $arItem['PROPERTIES']['LINK']['VALUE'] ?>" id="<span id=" title=" Код PHP: &lt;? $this-&gt;GetEditAreaId($arItem['ID']); ; ?&gt;"


    Весь вот этот блок со ссылкой отредактируйте и поправьте. От id= и дальше. Внутрь попали куски разметки визуального редактора битрикса.

    Скорее всего должно быть что-то типа
    <a href="<?= $arItem['PROPERTIES']['LINK']['VALUE'] ?>" 
       id="<?= $this->GetEditAreaId($arItem['ID']); ?>" 
       class="main-slider__item swiper-slide" 
       style="background-image: url();" 
       data-bx-app-ex-style="background-image: url(<?= $arFile['SRC'] ?> );">
        <div class="main-slider__content">
            <h1><?= $arItem['PROPERTIES']['CAPTION']['VALUE']; ?></h1>
            <?= $arItem['PREVIEW_TEXT']; ?>
        </div>
    </a>


    Вообще с битриксом очень хорошее правило - никогда не редактировать что-то, и имеющее в себе PHP-код, через визуальный редактор.
    Ответ написан
  • Почему Phpstorm запрашивает несуществующий путь к файлу?

    smilingcheater
    @smilingcheater
    Попробуйте отключить "виртуальный диск" в настройках опенсервера (Настройки, вкладка "Сервер", самая первая настройка). Опенсервер почему-то упорно думает, что установлен на диске E. После этого перезапустите опенсервер (возможно потребуется перезагрузиться).

    Либо пропишите конктеный путь до папки в расширениями:
    ПКМ на флажок опенсервера в трее - Дополнительно - Конфигурация - PHP
    откроется файл шаблона конфигурации (не самого конфига, а шаблона, из которого опенсервер при каждом запуске собирает свой конфиг. Так что после изменения этого файла обязательно перезапускать опенсервер)
    Ищите строку extension_dir=....
    У меня оно равно
    extension_dir = "%sprogdir%/modules/php/%phpdriver%/ext/"
    переменная sprogdir - "Генерируемый путь до папки с Open Server с учетом виртуального диска (слеш "/")" (описано в доках https://ospanel.io/docs/ )

    Надо заполнить переменную extension_dir реальным полным путём до папки \modules\php\PHP_7.1-x64\ext\ и перезапустить опенсервер, чтобы он перегенерировал файл конфига
    Ответ написан
  • Почему "array_walk_recursive" не срабатывает в данном случае?

    smilingcheater
    @smilingcheater
    Эм, ну как бы потому, что это array_walk_recursive.
    Если она встречает массив как значение текущего ключа - она в него заходит и начинает применять коллбек на скалярные элементы в нём.
    ---
    Итоговый вариант ответа: написать собственную рекурсивную функцию для обхода массива. Например вот так:
    function recursiveProcess($array) {
        foreach ($array as $key => $value) {
            if ($key == 'car' && is_array($value) && isset($value['color'])) {
                // Нашли!
            }
            
            if (is_array($value)) {
                // Встретили массив - заходим в него
                recursiveProcess($value);
            }
        }
    }
    Ответ написан
  • Каким образом можно оптимизировать запрос на выборку большого количества записей?

    smilingcheater
    @smilingcheater
    Вы сейчас сначала выбираете из базы все элементы с их свойствами (CIBlockElement::GetList), затем в цикле для каждого элемента дополнительно загружаете ещё раз все его свойства (CIBlockElement::getProperty), а затем ещё одним запросом в цикле получаете данные о связанном элементе (getElementByID), который будет везде одинаков т.к. вы выбираете с фильтрацией как раз по этому свойству.

    Я бы предложил сделать так: сначала загрузить все новости, собрать ID связанных типов спорта, потом подгрузить одним отдельным запросом нужную инфу по типам спорта, и распихать её по новостям. Примерный код будет такой:

    function sportNews($iblockId, $sportTypeId) {
        $arSelect = ["*", "PROPERTY_*", "PROPERTY_SPORT_TYPE"]; // Добавить в выборку поле типов спорта. Отдельно с указанием кода - чтобы можно было к нему обращаться по коду, а не по ID
        $arFilter = ["IBLOCK_ID" => $iblockId, "=PROPERTY_SPORT_TYPE" => $sportTypeId];
        $arItems  = [];
        $res      = CIBlockElement::GetList([], $arFilter, false, ["nPageSize" => 500], $arSelect);
    
        $sportTypes = []; // Массив, в который мы собираем ID связанных типов спорта
    
        while ($arItem = $res->fetch()) {
            $sportTypes = array_merge($sportTypes, $arItem['PROPERTY_SPORT_TYPE_VALUE']); // Собираем в массив
            $arItems[] = $arItem;
        }
    
    
        if (!empty($sportTypes)) {
            $sportTypes = array_unique($sportTypes);
            $arFilterSport = ['ID' => $sportTypes, 'IBLOCK_ID' => 'ИД Инфоблока типов спорта'];
            $resSport      = CIBlockElement::GetList([], $arFilterSport);
    
            $sportReference = [];
            while ($arItem = $resSport->fetch()) {
                $sportReference[$arItem['ID']] = $arItem; // Раскладываем выбранные типы спорта в ассоциативный массив по ID'шникам
            }
    
            foreach ($arItems as $ind => $arItem) { // Проходимся по всем новостям
                $arItems[$ind]['SPORT_TYPE'] = [];
                foreach ($arItem['PROPERTY_SPORT_TYPE_VALUE'] as $sportTypeId) {
                    $arItems[$ind]['SPORT_TYPE'][] = $sportReference[$sportTypeId]; // Рассовываем в них загруженные типы спорта
                }
            }
        }
    
        return $arItems;
    }
    
    $iblockId = 10; // ID инфоблок новости спорта
    $sportTypeId = 5; // ID элемента инфоблока виды спорта (футбол)
    sportNews($iblockId, $sportTypeId);
    Ответ написан
  • Поведение PHP На разных ОС?

    smilingcheater
    @smilingcheater
    Вы вызываете файл с этим кодом через браузер? Веб-окружение на винде настроено через что-то типа OpenServer?

    Скорее всего причина в том, что браузер автоматически делает ещё 1 запрос, на favicon.ico. На винде у вас настроено вероятно так, что статика типа иконки отдаётся через nginx, и запрос на иконку не попадает в этот Index.php, а на маке и убунте запрос обрабатывается апачем и попадает в index.php. Это можно проверить несколькими способами, например:
    1. через инструменты разработчика посмотреть запросы к серверу
    2. в логировании дополнительно записывать и запрашиваемый файл/урл. Либо весь $_SERVER для наглядности.
    3. положить рядом файл favicon.ico, и посмотреть не прекратились ли доп. записи
    Ответ написан
  • Через readfile() можно отдавать несколько файлов?

    smilingcheater
    @smilingcheater
    Вполне возможно что проблема с сессиями - PHP, при хранении сессии в файлах, подвешивает одновременные запросы кроме первого, пока первый не освободит сессию.
    Ответ написан
  • Как оптимизировать php код?

    smilingcheater
    @smilingcheater
    Например так. Задать массив, описывающий подходящие индексы и соответствующие им размеры, искать подходящий индекс через array_search и заполнять нужные переменные:
    $img_width = '';
    $img_height = '';
    $grid_num = '';
    
    $settings = array(
        array(
            'indexes'    => array(2, 4, 5, 11, 13, 14, 15, 16, 20, 21, 23, 24, 25, 27, 28, 31, 32, 35, 36, 38, 39, 41),
            'img_width'  => 100,
            'img_height' => 100,
            'grid_num'   => 1
        ),
        array(
            'indexes'    => array(1, 3, 7, 8, 9, 10, 12, 17, 19, 22, 26, 29, 30, 34, 37, 42),
            'img_width'  => 400,
            'img_height' => 500,
            'grid_num'   => 2
        ),
        array(
            'indexes'    => array(6, 18, 33, 40),
            'img_width'  => 430,
            'img_height' => 240,
            'grid_num'   => 3
        )
    );
    
    foreach ($settings as $setting) {
        if (array_search($count_block, $setting['indexes']) !== false) {
            $img_width  = $setting['img_width'];
            $img_height = $setting['img_height'];
            $grid_num   = $setting['grid_num'];
            break;
        }
    }
    Ответ написан