Ответы пользователя по тегу PHP
  • Как НЕ фиксировать транзакцию после отработки php скрипта?

    @alexalexes
    $_POST['SQL'];
    Ой, вы доверяете клиенту настолько, что позволяете ему самому формировать текст запроса для бэкенда?
    У такой модели взаимодействия уровень безопасности еще ниже, чем у подготовленных запросов со строковой склейкой параметров.
    Идеология выполнения скриптов в PHP такая, чтобы выполнить все атомарные действия, зафиксировать результат (или откатиться), отдать ответ и умереть.
    Есть какие-то примеры данного "фокуса"?

    Есть. Технология называется web sockets, она представляет другую идеологию - называется длинные запросы. Когда клиент открывает соединение с сервером и ждет от сервера сообщений (или сам их отправляет в соккет), при этом скрипт сервера в бесконечном цикле опрашивает открытый соккет. Не завершая скрипт, на сервере можно либо ожидать появление сообщения в соккете, либо выполнять что-то по транзакции, если имеется принятое сообщение.
    Проблема еще в том, что PHP не сильно приспособлен для этого режима. Вам придется делать бесконечную петлю обработки в скрипте:
    while(true)
    {
      // исполняемый код для всех клиентов соккетов
    }

    И вам нужно самим делать механизм сессий, чтобы отличать одного клиента от другого, поскольку запущенный скрипт будет принимать сообщения от всех клиентов.
    Для этих целей больше годится NodeJS. Там все соккеты разбиты по обработчикам событий, можно выделить контекст одного конкретного клиента.
    Резюмируя, могу сказать.
    а) Вы пишите свой продвинутый редактор запросов (а-ля PHPMyAdmin но с поддержкой транзакций) и у вас неправильно выбран вид сервера для бэкенда (PHP вместо NodeJS). Технические требования для взаимодействия клиента и сервера не имеют подходящей реализации технологии на сервере (web sockets).
    б) Либо у вас приложение не предполагает работы, связанной с редактированием запросов пользователем. Вы просто переносите опыт разработки desktop приложений на веб разработку.
    В этом случае вы не правильно делаете то, что формируете запросы на клиенте. Толстую бизнес-логику, предполагающую взаимодействие с базой данных с фиксацией или не фиксацией транзакции нужно переносить на бэкенд, либо в хранимые процедуры и функции СУБД.
    Ответ написан
    2 комментария
  • Как правильно заменить текст в html?

    @alexalexes
    Функция ViewGifImage не нативная, а скорее всего ее реализация прописана в какой-то подключаемой библиотеке JS.
    Нужно погуглить спецификацию этой библиотеки, и посмотреть в доках, за что отвечает параметры в функции ViewGifImage.
    Если я предположу (я не знаю, что за библиотека и не видел ее документации!), что первый параметр отвечает за указатель на html узел, куда вывалить бинарный ресурс изображения, то нужно как-то обозначить теги, чтобы указатели на эти теги выцепить из DOM через JS. Например, я хочу им задать уникальные идентификаторы:
    <img id="image-1234" src="/какой-то путь/qa_2023-02-01-212831-1.gif">
    <img id="image-5678" src="/какой-то путь/qa_2023-02-01-212831-2.gif">

    Тогда из DOM я буду доставать указатели на эти элементы через функцию getElementById.
    <script type="text/javascript">
    let image_1234 = document.getElementById("image-1234"); // тут получаем ссылку на элемент с id="image-1234"
    // далее, используем ее вместо this
    ViewGifImage(image_1234, 'sitedb/log/QA/General/SfpBCTuningCheck/gfx/qa_2023-02-01-212831-1.gif','sitedb/log/QA/General/SfpBCTuningCheck/gfx/qa_2023-02-01-212831-1.pix','322','242','ReflectionResultPlot','Frequency in MHz','0','Reflection Factor |r|','0','1','xffffff x000000 x000000 xff0000 x0000ff x00df00 xff00ff xff7f00','2','158','1','Reflection 0 Degrees','158','1','Reflection 90 Degrees','','','','','','','','','');
    
    let image_5678 = document.getElementById("image-5678"); // тут получаем ссылку на элемент с id="image-5678"
    // далее, используем ее вместо this
    ViewGifImage(image_5678, 'sitedb/log/QA/General/SfpBCTuningCheck/gfx/qa_2023-02-01-212831-2.gif','sitedb/log/QA/General/SfpBCTuningCheck/gfx/qa_2023-02-01-212831-2.pix','322','242','TransmissionResultPlot','Frequency in MHz','0','Transmission |t| in db','0','1','xffffff x000000 x000000 xff0000 x0000ff x00df00 xff00ff xff7f00','2','158','1','Transmission 0 Degrees','158','1','Transmission 90 Degrees','','','','','','','','','')
    </script>
    Ответ написан
  • Как правильно хранить секунды в базе даных?

    @alexalexes
    1. Храните в БД целочисленно;
    2. Передавайте на фронт целочисленно;
    3. На фронте преобразуйте целочисленную длительность в нужный формат любым доступным способом.
    Ответ написан
    Комментировать
  • Почему при использовании substr в php, если в тексте есть символ точки, то он считает не корректно?

    @alexalexes
    "ДокРу00001.Р1"

    Вероятно, у вас эта строка не в однобайтовой кодировке (скорее всего в utf8 работаете).
    Для таких строк нужно использовать набор функций для строк в многобайтовых кодировках, в данном случае вам нужна функция mb_substr вместо substr, иначе результат работы функций для однобайтовых кодировок в строках с многобайтовыми - не предсказуем.

    PS: не забудьте включить расширение mb_string в конфиге php сервера.
    Ответ написан
  • Как узнать процент похожести текста?

    @alexalexes
    Самое простое - натравить поисковик на собственный ресурс запросом:
    "site:yousite.ru фрагмент фразы".

    PS: Сайт на момент запроса должен быть проиндексирован поисковиком.
    Ответ написан
    Комментировать
  • Как получить имя файла из zip архива, который содержит кириллицу?

    @alexalexes Автор вопроса
    Имя файла, получаемое при работе с модулем ZipArchive, из-за бага в этом модуле требует некоторого преобразования через промежуточные однобайтовые кодировки.
    Нужно провести такую цепочку преобразований:
    UTF-8 -> encode1 -> encode2 (encode3) -> UTF-8
    В php это будет так:
    $out_str = iconv('UTF-8', $encode1.'//IGNORE', $in_str);
    $out_str = iconv($encode1, $encode2.'//IGNORE', $out_str);
    $out_str = iconv($encode3, 'UTF-8//IGNORE', $out_str);

    Но проблема в том, что для каждой конфигурации сервера эти кодировки могут отличаться.
    Чтобы их найти нужно воспользоваться методом перебора.
    Для начала найдем все кодировки, которые поддерживает функция iconv.
    Для этого в консоли сервера вызовем:
    $ iconv -l
    Из набора кодировок нужно взять только те, которые содержат наименование "CPxxx", где xxx - число.
    С помощью скрипта провести полный перебор:
    $all_encoding = []; // сюда вставляем список всех кодировок iconv
    $out_encoding = array_filter($all_encodings, function($item){return strpos(strtolower($item), 'cp') !== false;});
      foreach($out_encoding as $encode1)
      {
        foreach($out_encoding as $encode2)
        {
          foreach($out_encoding as $encode3)
          {
              $str = iconv('UTF-8', $encode1.'//IGNORE', $out);
              $str = iconv($encode1, $encode2.'//IGNORE', $str);
              $str = iconv($encode3, 'UTF-8//IGNORE', $str);
              if($str !== false && $str !== '')
                echo $encode1.'::'.$encode2.'::'.$encode3.'::'.$str.'<br>';
          }
        }
      }

    Визуально ищем тот вариант, где имя файла восстановилось.
    В моем случае это:
    UTF-8 -> cp437 -> cp437 (cp866) -> UTF-8
    В коде это выглядит так:
    $out_str = iconv('UTF8', 'CP437//IGNORE', $in_str);
    $out_str = iconv('CP437', 'CP437//IGNORE', $out_str);
    $out_str = iconv('CP866', 'UTF8//IGNORE', $out_str);
    Ответ написан
    Комментировать
  • Зачем вложенные "namespace"?

    @alexalexes
    Потому, что класс user (с достаточно неуникальным именем) может реализован еще в каком-нибудь стороннем компоненте.
    Чтобы при подключении этого компонента, вы могли использовать одноименный класс user как из своего компонента, так и из стороннего.
    Ответ написан
  • Почему не вносятся изменения в БД?

    @alexalexes
    1. Нужно использовать подготовленные запросы, а не делать по старинке через mysqli_real_escape_string.
    2. Если вы текстом написали запрос update, он еще не начнет выполнятся, где-то нужно запустить execute.
    if(isset($_POST['ref_button']) )
    {
        $send_ref = $_POST["send_ref"];    
        $stmt = msqli_prepare($con, "SELECT * FROM usertable WHERE referral= ?");
        mysqli_stmt_bind_param($stmt, 's', $send_ref);  // s - тип данных строка, i - число, если не тот тип данных - нужно исправить
        $result = mysqli_stmt_execute($stmt);
        if(mysqli_num_rows($result) > 0)
        {
            $stmt = msqli_prepare($con, "UPDATE usertable SET owner = ? WHERE email = ?");
            mysqli_stmt_bind_param($stmt, 'ss', $send_ref, $email); // s - тип данных строка, i - число, если не тот тип данных - нужно исправить
            $result = mysqli_stmt_execute($stmt);
        }
    }
    Ответ написан
    Комментировать
  • Почему sql запрос не определяет имя таблицы, если записывать имя через prepare?

    @alexalexes
    1. В качестве входных параметров никогда не использовались имена таблиц в подготовленных запросах - это попытка забивать микроскопом гвозди.
    2. Метки для входных параметров - это не тип данных, это просто название места куда будет подставлено значение этой метки по ключу из массива значений.
    Причем, именованные метки нужно связывать со значением с помощью специальной функции:
    $stmt = $db->prepare("SELECT * FROM moya_tablitsa WHERE id = :metka_parametra_identifikatora");
    $stmt->bindParam(':metka_parametra_identifikatora', 123);
    $stmt->execute();

    Но можно не использовать именованные метки (если их несколько в запросе, то нужно вставлять значения по порядку)
    $stmt = $db->prepare("SELECT * FROM moya_tablitsa WHERE id = ?");
    $stmt->execute([123]);

    Можно использовать связывающую функцию, указав порядок метки.
    $stmt = $db->prepare("SELECT * FROM moya_tablitsa WHERE id = ?");
    $stmt->bindParam(1, 123); // 1 - это номер метки, 123 - значение параметра
    $stmt->execute();
    Ответ написан
    Комментировать
  • Как правильно указать цикл для вывода только домена?

    @alexalexes
    for($i = 0; $i < count($api['answer']['result']); $i++)
      echo $api['answer']['result'][$i]['domains'][0]['fqdn'];

    По хорошему, нужно бы еще проверять есть ли массив результата по $api['answer']['result'], если массив в $api['answer']['result'][$i]['domains'].
    Ответ написан
  • Как сделать фото с камеры HTML js?

    @alexalexes
    Комментировать
  • Как пересобрать ссылку php?

    @alexalexes
    Вот способ с parse_url, вместе с вариантами обработки ошибок.
    $url_comps = parse_url($url, PHP_URL_HOST | PHP_URL_PATH);
    if(!isset($url_comps['host']) || $url_comps['host'] !== 'music.yandex.ru')
    {
      echo 'Не Яндекс.Музыка!';
       exit;
    }
    if(!isset($url_comps['path']) || strllen($url_comps['path']) == 0 || strpos($url_comps['path'], 'album') === false || strpos($url_comps['path'], 'track') === false)
    {
      echo 'Нет параметров альбома и трека!';
    }
    $url_path_params = explode('/', $url_comps['path']);
    $url_path_params_count = count($url_path_params);
    $album = null; $track = null;
    
    for($i = 0; $i < $url_path_params_count; $i += 2)
    {
      if(isset($url_path_params[$i]) && isset($url_path_params[$i + 1]) && is_numeric($url_path_params[$i + 1]))
      {
        if($url_path_params[$i] === 'album')
           $album = $url_path_params[$i + 1];
         if($url_path_params[$i] === 'track')
           $track = $url_path_params[$i + 1];
      }
    }
    if(is_null($album))
    {
      echo 'Не задан числовой параметр альбома!';
      exit;
    }
    if(is_null($track))
    {
      echo 'Не задан числовой параметр трека!';
      exit;
    }
    $output = "https://music.yandex.ru/iframe/#track/".$album."/".$track."/";
    Ответ написан
  • Как переписать код в PDO?

    @alexalexes
    Нужно заменить на PDO аналоги функций в этих строчках:
    $conn = mysqli_connect("localhost", "root", "", "db_user");
    ...
    $sql = "SELECT * FROM users WHERE email = '".$email."' AND apiKey = '".$apiKey."'"; // а тут нужно использовать подготовленный запрос для того, чтобы безопасно добавить параметры 
                    $res = mysqli_query($db, $sql); // в подготовленном запросе на этом месте у вас будет execute-метод
                    if (mysqli_num_rows($res) != 0) {
                        $row = mysqli_fetch_assoc($res);
    ...

    PS: Вероятно, у вас проблема не в PDO, а в вообще, как переписать в подготовленный запрос.
    Ответ написан
  • Как правильно использовать функции array_filter() и in_array()?

    @alexalexes
    Не знаю, как на стрелочных функциях, но на классической анонимной функции внутрь ее контекста нужно передавать доп. аргументы через use (замыкание):
    $array2_ = array_map(function($row){return $row['value'];}, $array2); // тут бы value вытащить в отдельный массив
    $result = array_filter($array1, function($row) use ($array2_) {return in_array($row['code'], $array2_);});
    Ответ написан
    Комментировать
  • PHP. Вместо символа кириллицы печатается заменяющий символ �. Как исправить?

    @alexalexes
    Нужно сообщить браузеру, в какой кодировке будет страница, при помощи http-заголовка:
    header('Content-Type: text/html; charset=utf-8');
    Так как присутствия
    <meta charset="utf-8" />
    недостаточно, если браузер взаимодействует с php сервером.
    PS:
    // $lastSymmbol = substr($ar['surname'], -1);
    Помните, что для utf-8, как для разновидности двухбайтовой кодировки, нужно использовать другой спектр функций mb_*, в данном случае mb_substr.
    Но чтобы одни работали, нужно убедиться, что включено расширение mbstring в настройках php.
    Ответ написан
  • Заморозка сервера в конец срока оплаты?

    @alexalexes
    У PHP сервера есть настройка в конфиге php.ini - макс. время выполнения скрипта - max_execution_time.
    Для долгоиграющих скриптов, обычно, разработчики либо в конфиге (повлияет на все скрипты), либо в htaccess (повлияет на скрипты в пределах каталога), либо в самом скрипте через функцию set_time_limit() корректируют этот параметр, чтобы таким скриптам хватило время на выполнение. Выкручивать этот параметр не нужно для всего сервера, иначе если в частонагруженных скриптах будут проблемы по зацикливанию, то их зависание скушает всю оперативную память сервера при многократном запуске.
    Ответ написан
  • Куда передаются и как извлечь данные через FETCH()?

    @alexalexes
    Объясните простыми словами новичку в javascript, куда передаются данные через fetch

    Данные передаются из браузера (он же клиент) передаются на сервер.
    Постоянно вижу разные примеры кода и везде прописывают файл назначения разным

    Это не файл, это url - адрес на сервере, от которого любым способом запустится какой-то скрипт, который сможет сформировать ответ для браузера (то есть для клиента).
    Если в url указан путь к файлу на сервере, то сервер может отдать статичный файл - но для сервера не принципиально, что отдавать по какому url, можно настроить любые правила взаимодействия.
    А ловят данные вообще через какой-то "php://input"

    Сервер ловит обращение по url (он же запрос), выясняет по настройкам, что нужно сделать: запустить серверный скрипт, отдать статичный файл или ответить каким-нибудь статусом (например, 404). Если по url запрос попадает на запуск скрипта, то в этом скрипте вы можете обработать параметры запроса. Параметры запроса как правило вылавливают в $_GET или $_POST, либо парсят часть url, либо в дополнение смотрят вложения $_FILES.
    Либо в вашем варианте смотрят сырцы запроса через php://input, если что-то нестандартное нужно обработать.
    Тогда зачем вообще эти файлы, которые указывают в Fetch? Причем одни с абсолютным адресом, другие с относительным, где-то указывают расширение (html, json и т.д.), где-то вообще без него.

    Сервер может отдать разные данные клиенту. Где-то их можно забрать из файла статично, где-то сгенерировать ответ серверным скриптом динамично. А можно на статичные пути генерить динамичные данные, по виду url это мало чего говорит.
    Нужно создавать файл какой-то на сервере в который якобы будет передаваться эта информация из JS через POST запрос?

    Да, на сервере должен быть скрипт, который сформирует ответ, если для клиента нужно сформировать нечто динамическое, зависящее от параметров запроса.
    Я создаю, у меня не выходит ничего, значение, при чтении этого файла или php://input (file_get_contents("php://input")) после передачи POST пустое.

    Указываете на клиенте метод POST - на сервере ловите параметры методом POST он будет в $_POST.
    Отправляете параметры GET или вшиваете их в url - ловите параметры на сервере в $_GET.
    Вкладываете файл на клиенте - получаете атрибуты файлов на сервере в $_FILES.
    Все просто.
    На клиенте:
    fetch('/foranswer.php', { //указываете скрипт на сервере, который сформирует ответ для клиента
                                                method: 'POST',
                                                headers: {
                                                    'Content-Type': 'text/plain'
                                                },
                                                body: player.signature
                                            });

    На сервере:
    Скрипт foranswer.php
    <?php
    var_dump($_POST); // Посмотрите, а что вообще пришло в пост параметрах.
    // Например, вам нужен параметр param1, забираем его значение из поста
    $param1 = isset($_POST['param1']) ? $_POST['param1'] : null;
    // Если param1 задан - что-то делаем
    if(!is_null($param1))
    {
      // Например, при наличии параметра param1 нужно прочитать некий ресурс на сервере
      $out = file_get_contents("/file.txt");
      // и отдать его содержимое клиенту
      echo $out;
    }
    else
    {
      // Нет обязательного параметра, отдаем ответ клиенту, что что-то не так.
      echo "Нужен обязательный параметр param1";
    }
    ?>
    Ответ написан
    1 комментарий
  • Как поменять формат вывода json?

    @alexalexes
    Попробуйте использовать опцию JSON_FORCE_OBJECT в функции json_encode.
    https://www.php.net/manual/ru/json.constants.php
    Добавлено:
    Ну, тогда item-ы кодируйте стандартной функцией, а сборку массива делайте кастомную:
    $imported_items[] = json_encode($product, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_FORCE_OBJECT);
    ...
    $preview_items[] =  json_encode($preview_product, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_FORCE_OBJECT);
    ...
    file_put_contents(sprintf(IMPORT_FILE, $id), '['.join(',', $imported_items).']');
    file_put_contents(sprintf(PREVIEW_FILE, $id), '['.join(',', $preview_items).']');
    Ответ написан
    1 комментарий
  • "Сырые строки" в php. Есть ли такое?

    @alexalexes
    Heredoc в php?
    $a = <<<THISISHEREDOC
    
    THISISHEREDOC;
    Ответ написан
    Комментировать
  • Как перевести дату в секунды если доступен только год?

    @alexalexes
    Вариант 1.
    1. Определите, что у вас - полная дата, или только год.
    2. Если только год, то приклейте 1 января.
    3. Конвертируйте в отметку Unix time как обычно.
    4. Если дата с фрагментом 1 января, то считаем, что известен был только год, выводим только год.

    Вариант 2.
    1. Определите, что у вас - полная дата, или только год. Результат сохраняем во временную переменную 1 - полная дата, 2 - только год.
    2. Если только год, то приклейте 1 января.
    3. Конвертируйте в отметку Unix time как обычно.
    4. Сохраните и отметку времени и результат выполнения шага 1 в отдельном поле (полная дата, или только год).
    5. Если полная дата, то конвертируем отметку времени в строковое представление, и берем всю строку. Если только год, то тоже конвертируем, но выводим только год.
    Ответ написан
    5 комментариев