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

    @alexalexes
    Самый простой концепт:
    1. При успешной авторизации создаем переменную cookie с временем жизни равным времени жизни сессии, с доступом http only, с идентификатором сессии.
    2. Если пользователь разлогинивается, то уничтожаем переменную cookie с идентификатором сессии.
    3. При генерации страницы в php, где нужно вывести статус авторизации, проверяем наличие живой куки.
    4. Если совершаем действие, требующее авторизации, дополнительно проверяем время жизни сессии в базе данных (если такой учет ведется).
    Ответ написан
  • Зачем нужен символ "&" перед функцией?

    @alexalexes
    Ответ написан
    Комментировать
  • Как лучше реализовать вывод в корзину?

    @alexalexes
    1. Ограничьте количество предметов в корзине каким-то макс. значением, оно должно быть явно задано, но не вызывало дискомфорта у пользователей (оно должно иметь такое значение, чтобы в нормальных человеческих условиях оно едва достижимо).
    $max_cart_item_count = 500;
    $curr_cart_item_count = min(count($_SESSION['cart']), $max_cart_item_count);
    for($i = 0; $i < $curr_cart_item_count; $i++)
    ....

    2. Есть опасность применения SQL инъекций.
    В этом месте, где подставляется переменная в текст запроса, если умело закомментировать кавычку, то можно получить полный доступ к базе.
    WHERE `type`= '$id'
    Избегайте подставлять любые переменные с пользовательскими данными в текст запроса ("с пользовательскими данными" и "в текст запроса" - нужно подчеркнуть и осмыслить как отдельные понятия с точки зрения безопасности). Для этого существует специальные методики подготовки запроса:
    $stmt = $conn->stmt_init();
    $stmt->prepare("SELECT * FROM `items` WHERE `type` = ?"); // подставляем текст запроса, причем на месте входных параметров ставим специальные маркеры - плейсхолдеры.
    $stmt->bind_param("i",  $id); // подставляем на место плейсхолдера значение параметра как целочисленный тип
    $stmt->execute(); // вот теперь можно выполнить запрос
    $result = $stmt->get_result();
    while($row = $result->fetch_assoc())
    {
     // Обработка результатов
    }
    Ответ написан
  • Отправка изображения canvas на сервер PHP?

    @alexalexes
    btn_send.addEventListener('click',async() => {
        let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
        let formData = new FormData(); // Создаем объект формы для наполнения данными, словно мы работаем с тегом form в html.
        formData.append('canvas_field', blob, 'canvas.png'); // это эквивалент тому, что в нашей html форме создаем поле input type="file" name="canvas_field" value="canvas.png" и прикрепляем туда содержимое blob (метод append сам расшаривает blob, дополнительных преобразований не требуется). Естественно, на DOM-дереве это никак не отразится, это модель формы в памяти JS.
        let response = await fetch('web_tp_word.php', {
        method: 'POST',
        body: formData // для fetch не нужно дополнительных параметров, чтобы объяснить как работать с formData. Идеально, чтобы завернуть файл в форму и отправить на сервер.
        });
    });

    На стороне сервера:
    var_dump($_FILES['canvas_field']); // Сервер при вызове скрипта сложит данные файла во временный файл, а как их получить - в $_FILES. Далее можно обрабатывать всеми теми способами, предназначенные для работы с $_FILES. И после уже неважно, как их сгенерировали на клиенте.
    Ответ написан
    1 комментарий
  • Почему не стоит передавать аргументы в функцию по ссылке?

    @alexalexes
    В отдельных задачах только передача по ссылке и спасет, если стоит цель не хапнуть лишней оперативной памяти при выполнении скрипта.
    Например, вам нужно обработать массив с over9000 элементами какой-то отдельной функцией. При существовании этого массива съедается 70% оперативной памяти. Вот тут вам ссылка на этот массив в помощь.
    Ответ написан
    Комментировать
  • Как правильно изменить sql запрос чтобы считывать данные с двух строк одной базы данных?

    @alexalexes
    Если предположить, что в таблице _post_extras есть столбец user_id, при этом данная таблица хранит расширенные сведения о записях другой таблицы - _post, каждая запись которой связана с первой таблицей отношением 1 к 1, через ключ post_id (название столбца-ключа как с первой таблицей, так и со второй автор не сообщал, но такая связь обязана существовать), получается следующее:
    SELECT SUM(rating) as rating, SUM(vote_num) as num
      FROM " . PREFIX . "_post_extras as pe
      inner join " . PREFIX . "_post as p on p.post_id = pe.post_id -- тут название ключей post_id с обеих сторон нужно уточнять!
    WHERE pe.user_id ='{$id}'
         and p.category = '{$category_id}'

    Также нужно уточнить автору, что должен вернуть запрос. Данный запрос вернет суммарный рейтинг и голосов по конкретному пользователю в конкретной категории публикаций.
    Ответ написан
    Комментировать
  • Как записать данные из запроса VK в бд?

    @alexalexes
    Отработать навык, как вставить в базу вообще что-то.
    Например, так https://html5css.ru/php/php_mysql_insert.php
    Обратите внимание, что у процесса взаимодействия с БД есть несколько фаз работы:
    подключение к базе, формирование запроса, добавление параметров к запросу, выполнение запроса и получение результата (если нужен действия статус или выборка).
    Ответ написан
    Комментировать
  • Как сделать проверку наличия слов?

    @alexalexes
    Самый тупой вариант без регулярок:
    $email_exploded = explode('@', $email);
    if(count($email_exploded) == 2 && ($email_exploded[1] == 'gmail.com' || $email_exploded[1] == 'mail.ru'))
    {
      echo 'Домен в порядке, проходите!';
    }
    Ответ написан
    Комментировать
  • Как сохранить writeImage все файлы директории?

    @alexalexes
    $imagick->writeImage('*.webp');
    У вас имя файла на протяжении всего цикла одно и то же.
    Чему вы удивляетесь, когда файл перезаписывается несколько раз, и остается последний перезаписанный вариант?
    Решение:
    1. Нужно посмотреть, что выводится в $ext:
    var_dump($ext);
    2. Если это действительно имя открытого файла, то самое грубое решение, добавить нужное расширение в конце, несмотря на наличие jpg.
    $imagick->writeImage($ext.'.webp');
    3. Хорошо бы посмотреть файл лога ошибок php - error_log. Возможно, есть еще какие-то проблемы с записью файлов.
    Ответ написан
  • Как сделать посуточный счетчик посещений (доработать старый)?

    @alexalexes
    Если вы понимаете, что делает этот запрос:
    UPDATE article SET visits=(visits+1) WHERE id='".$theme_idss."' LIMIT 1

    То по аналогии можно плюсовать интересуемый столбец:
    UPDATE article
    SET visits=(visits+1),
          today = today + 1 -- суточные посещения
     WHERE id='".$theme_idss."' -- когда разберетесь, что такое sql-инъекция, то перепишите все запросы, использующие такой стиль подстановки параметров (склеиванием строк)
    LIMIT 1 -- после того, как разберетесь, является ли id первичным ключом, можно убрать лимит

    Но при добавлении столбца нужно позаботиться, чтобы у столбца значение по умолчанию было 0.
    ALTER TABLE article
    ADD COLUMN today int default 0 AFTER visits

    В скрипте, который чистит таблицу раз в сутки предусмотрите запрос, обнуляющий суточный счетчик у всех статей:
    UPDATE article
    SET today = 0

    PS: Если хотите анализировать посещаемость, то лучше воспользоваться готовыми счетчиками от поисковых систем - Google Analytics или Яндекс-метрики.
    Если хотите все же использовать свой лог, то лучше его не удалять. Вдруг захотите выявить среднемесячное/суточное/годовое посещение или в каком то другом разрезе по разным разделам сайта. Для пересчета понадобится каждая запись посещения.
    Ответ написан
    2 комментария
  • Как получить значение элемента, зная его id в xml?

    @alexalexes
    Вам нужно оперировать двумя запросами к xml-дереву:
    1. Определить список узлов, для которых известны категории:
    //items/item[categoryId=//catalog/category/@id]
    2. Определить категорию узла при переборе результата запроса 1.
    //catalog/category[@id="тут вставляем код категории"]

    При вставке узла categoryname нужно ориентироваться не на categoryId, а на portal_category_id, поскольку вставлять новый узел до существующего легче, чем изобретать велосипед с функцией, которая делает вставку после.
    PS: Вопрос выглядит как задание, характерное для фриланса, поэтому можно только посоветовать, как его реализовать, без подробной реализации.
    Ответ написан
    Комментировать
  • Безопасно ли такая авторизация и последующее открытие страниц?

    @alexalexes
    Эта конструкция небезопасна, если у программиста кривые руки.
    if($rows) {
    $logged = true;
    } else {
    $logged = false; 
    }
    } 
    else {
    $logged = false;
    }

    Статус авторизации очень критичен, и если возникает какая-нибудь ошибка в его проверке, то лучше, чтобы по умолчанию он оставался в значении "не авторизован", то есть false.
    С точки зрения безопасности системы, если произойдет какая-нибудь ошибка, то пользователь лучше не дополучит свой статус, чем случайно получит уровень выше привилегий.
    Поэтому до всяких проверок, инициируете состояние по умолчанию, а потом, выстрадав все проверки присваиваете true.
    // Секция, где присваиваются значения по умолчанию основных переменных
    $logged = false;
    .....
    ....
    // начинаем проверку
    if(первое условие)
    {
      if(второе условие)
      {
        if(еще какое-то супер-пупер условие)
        {
           $logged = true; // вот теперь, пройдя все медные трубы, мы изменяем статус
        }
      }
    }
    Ответ написан
    6 комментариев
  • Как найти точку пересечения графиков?

    @alexalexes
    Можно. Но реализовать это можно многими путями.
    Вариант А.
    Серверная часть (то бишь PHP) подготавливает как данные, так и графику.
    Это значит, что вы на серверном скрипте как вычисляете все необходимые точки, так и рисуете график, например GD-библиотекой.
    а) Создаете графическое полотно.
    б) Рисуете в этом полотне необходимые линии.
    в) Возможно, где-то что-то подписываете.
    г) Отдаете клиентской части приложения (то бишь браузеру) бинарный поток файла изображения.
    Самый топорный вариант, исследователь графика будет иметь на руках только картинку, ни смаштабировать, и изменить какие-нибудь атрибуты отображения он не сможет. Единственное преимущество - процесс вычисления графика доступен только вашему скрипту, и никто не сможет провести реверсинжиниринг, если захочет разобраться как вы его генерируете.
    Вариант Б.
    На стороне сервера делаете аналитику, отдаете браузеру готовый html-документ, содержащий canvas с генерированными на стороне сервера векторными объектами (линии графика) в svg формате. Это тоже топорный, но уже промежуточный вариант между А и В. Единственное преимущество - все данные векторные, поэтому они будут легковесны для передачи и воспроизведения в браузере.
    Вариант В.
    На стороне сервера делаете аналитику, отдаете данные о вычисленных точках клиенту в виде json, а на клиенте рисуете график в какой-нибудь js-библиотеке. Выбор библиотек широк: chart.js, D3.js и т.д.
    Это самый прогрессивный вариант, поскольку на клиенте можно менять масштаб в окне просмотра графика, менять какие-нибудь атрибуты этого просмотра и т.д.
    Ответ написан
    1 комментарий
  • DELETE FROM list WHERE id = 'id строки в списке дел'. Как мне указать этот id?

    @alexalexes
    1. Подготовить текст запроса prepare-функцией.
    2. Присобачить нужные параметры запроса bind-функцией.
    3. Выполнить запрос execute-функцией.
    Запрос не выполняется? Посмотреть ошибки.
    PS: В любой непонятной ситуации читай документацию.
    Ответ написан
    Комментировать
  • Как лучше сравнить два файла изображения?

    @alexalexes
    Фишка хэширования в том, что вы считаете его ровно один раз, и при повторном сравнении уже оперируете им, а не содержимым файла.
    У вас есть 1 млн. файлов. При получении каждого файла вы подготовили для него хэш и сохранили этот хэш в отдельном массиве в оперативной памяти, в файле на диске или в таблице базы данных.
    Когда поступит следующий файл, то вы от него тоже получите хэш, но при сравнении вам уже не надо вычитывать 1 млн. файлов, чтобы сделать сравнение, достаточно обратиться к более быстрому источнику за хэшами этих файлов, сравнение которых будет короче и перебор быстрее (если эта база данных, то должны использоваться индексы, если оперативная память, то сбалансированные деревья и бинарный поиск и т.п.).
    Ответ написан
    1 комментарий
  • Как правильно сформировать регулярное выражение php?

    @alexalexes
    Просто взял регулярку из ответа.
    <a\s.*?href="(.+?)".*?>\[photo-.+<\/a>
    И методом тыка подобрал в онлайн редакторе.
    Ответ написан
  • Как из массива объектов удалить дублирующиеся объекты?

    @alexalexes
    Можно удалить id из элемента массива (точнее из копии элемента), оставшиеся свойства засериализовать, от сериализации найти md5 хэш - это и будет ориентир для уникальности элемента.
    $out_array = [];
    foreach($donates as $donate)
    {
       $donate_copy =  $donate; // копируем элемент массива
       unset( $donate_copy->id); // удаляем уникальное свойство из элемента
       $key = md5(serialize($donate_copy)); // получаем уникальный ключ по содержанию остальных свойств
       $out_array[$key] =  $donate; // добавляем исходный элемент в новый массив по уникальному ключу
    }
    Ответ написан
    2 комментария
  • Как выдавать пустую страницу в PHP?

    @alexalexes
    Проблема такой защиты от DDOS на PHP в том, что атакующий пользователь все же успевает запустить скрипт на PHP, хоть и с минимальными ресурсами. Если у вас архитектура серверного приложения построена не на event loop (как правило, обычные сайты), то для каждого запущенного скрипта выделяется отдельный системный процесс - не самый экономный вариант работы PHP сервера.
    Поэтому, нерадивых пользователей лучше отшивать как можно раньше.
    Идентифицировать плохого пользователя вы можете и на PHP, а вот работу по его отсечению лучше доверить системе, которая стоит перед PHP сервером. Это может быть и Apache, и Nginx.
    Определяете пользователя и добавляете его в файл черного списка по IP, user agent или cookie, который будет обрабатывать настроенный Apache или Nginx.
    Лучше конечно, чтобы это был отдельный файрвол, еще лучше - на железке (но в условиях арендуемого хостинга такое маловероятно).
    Ответ написан
    Комментировать
  • Как вытащить информацию из XML вне зависимости от используемых неймспейсов?

    @alexalexes
    Читаете каждый узел, определяете его имя, читаете его атрибуты.
    Если элемент имеет признаки определителя неймспейсов, например, называется export и имеет атрибуты xmlns:ns*, то это и есть определитель наймспейса. Нашли определитель, останавливаете поиск определителя.
    Возможно, для дальнейшего чтения нужно взять этот список атрибутов и искать только этих потомков.
    PS: Термин определителя неймспейсов взят от балды. Для такой структуры данных нужна вполне определенная техническая документация, которая должна давать исчерпывающий ответ, как ее использовать.
    Ответ написан
    1 комментарий
  • Почему Удаляются записи из БД, ООП, php?

    @alexalexes
    ... на глобальном сбой.

    Вероятно, нужно докопаться до текста ошибки, чтобы понять, в чем дело?
    Но можно предположить, что от места выполнения у вас чувствительна вот эта строчка:
    $this->go_to_back_one_stap = explode('.ru', $_SERVER['HTTP_REFERER']);

    Выведите в отладочный файл значение $_SERVER['HTTP_REFERER'] на боевом окружении и посмотрите, то ли вы ожидаете в ней значение, чтобы разделить ее по '.ru' и взять элемент с индексом 1.
    Ответ написан