За последние 24 часа нас посетили 23786 программистов и 1386 роботов. Сейчас ищут 1120 программистов ...

Задержка смены анекдотов. Как реализовать?

Тема в разделе "PHP для новичков", создана пользователем Евгений Владимирович, 29 май 2024.

  1. Евгений Владимирович

    Евгений Владимирович Активный пользователь

    С нами с:
    3 май 2009
    Сообщения:
    28
    Симпатии:
    0
    Есть простой скрипт
    Выводящий анекдот из файла
    Подключается через include_once
    При каждом обновлении страницы- новый анекдот соответственно
    Подскажите
    Как ограничить смену анекдотов, чтобы за одну секунду не могло выводиться 25 анекдотов например одному пользователю при перезагрузка х страницы. Как это реализовать. Чтобы стояла задержка смены - не чаще одного анекдота в три секунды например ??
    Сам скрипт:
    <?php
    $file = file('anekdot.dat');
    $max_rnd = count($file);
    $rnd_frase = mt_rand(1,$max_rnd);
    $content = "<div>".$file[$rnd_frase]."</div>";
    $content1 = mb_convert_encoding($content, 'windows-1251', 'utf-8');
    echo $content1;
    ?>
     
  2. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.840
    Симпатии:
    743
    Адрес:
    Татарстан
    1. Чтоб однозначно определить - тот же это пользователь или нет, нужно применять регистрацию, авторизацию. Если для неавторизованнвх хотите - та еще заморочка.... нужно цифровой слепок барузера делать через js, еще можно к ip привязываться
    2. Нужно где-то хранить счетчик показа анекдотов для конкретного пользователя - или записывать в файл или лучше в БД. Записываете время просмотра для каждого просмотра. При записи, предварительно удаляете те элементы - которые уже не укладываются в ваш временной интервал
    3. Перед выводом анекдота - смотрите кол-во записей о просмотре данным пользователем - смотрите - все ли они укладываются в аш промежуток - и только если так - показываете

    вот так ... такая вроде-бы простая формулировка задачи - влечет нехилые затраты.

    Подумайте - а оно вообще вам надо? Ну посмотрит 40 анекдотов - жалко чтоли? )))
     
  3. Survivor

    Survivor Новичок

    С нами с:
    8 фев 2023
    Сообщения:
    77
    Симпатии:
    15
    Если прям не упарываться, вряд ли ты банкир, желающий рассмешить своих клиентов.
    Этого может быть вполне достаточно.

    anekdot.php
    PHP:
    1. <!DOCTYPE html>
    2. <html lang="ru">
    3. <head>
    4.     <meta charset="UTF-8">
    5.     <title>Анекдоты</title>
    6.     <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    7.     <style>
    8.         #anekdot-container {
    9.            font-size: 20px;
    10.             margin: 20px;
    11.         }
    12.     </style>
    13. </head>
    14. <body>
    15.     <div id="anekdot-container">Загрузка анекдота...</div>
    16.  
    17.     <script>
    18.         function show_anekdot()
    19.         {
    20.             $.ajax({
    21.                 url: 'ajax_anekdot.php',
    22.                 type: 'POST',
    23.                 dataType: 'json',
    24.                 success: function( data )
    25.                 {
    26.                     if (data.error)
    27.                     {
    28.                         return $('#anekdot-container').text(data.error);
    29.                     }
    30.  
    31.                     if ( data.anekdot )
    32.                     {
    33.                         $('#anekdot-container').html("<div>" + data.anekdot + "</div>");
    34.                         //- можно использовать append
    35.                     }
    36.                 },
    37.                 error: function()
    38.                 {
    39.                     $('#anekdot-container').text('Ошибка при загрузке анекдота.');
    40.                 }
    41.             });
    42.         }
    43.  
    44.         // Отображение первого анекдота сразу после загрузки страницы
    45.         show_anekdot();
    46.  
    47.         // Показываем новый анекдот каждые 10 секунд
    48.         setInterval(show_anekdot, 10000);
    49.     </script>
    50. </body>
    51. </html>

    ajax_anekdot
    PHP:
    1. <?php
    2. declare(strict_types = 1);
    3. header('Content-Type: application/json');
    4.  
    5. if ( $_SERVER['REQUEST_METHOD'] == 'POST' )
    6. {
    7.   $anekdot = file('anekdot.dat', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    8.  
    9.   // Проверка на наличие анекдотов
    10.   if ( $anekdot === false || empty( $anekdot ) )
    11.   {
    12.     exit( json_encode(['error' => 'Не с чего ржать']) );
    13.   }
    14.  
    15.   // Возвращаем анекдот в формате JSON
    16.   exit ( json_encode(['anekdot' => $anekdot[array_rand($anekdot)]]) );
    17. }
    Файл с анекдотами
    Код (Text):
    1.  
    2. Анекдот 1
    3. Анекдот 2
    4. Анекдот 3

    Ну, а если прям хочешь защититься:
    - Проверяй заголовки $_SERVER['HTTP_ORIGIN']
    - Создай какой-нибудь ключик api и проверяй его в ajax файле
    - Если регистрации нет, можно json файлик с сохранением IP юзера (+ чего угодно ещё) и ограничением кол-ва запросов
    либо pid файлик и ограничивать вообще всех))
     
  4. Serg197211

    Serg197211 Новичок

    С нами с:
    23 фев 2024
    Сообщения:
    4
    Симпатии:
    1
    Зачем такие сложности? Всё можно в сессии хранить. В начале скрипта session_start(), и хранить в сессии ассоциативный массив, например "номер анекдота" => timestamp показа. И при показе соответственно учитывать информацию из этого массива
     
  5. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    331
    Симпатии:
    66
    Адрес:
    Бавария, Германия
    Добрый день!
    Вы отправляете по ajax-запросу только одну строку из файла $anekdot
    PHP:
    1.  exit ( json_encode(['anekdot' => [array_rand($anekdot)]]) );
    Не понятно зачем для этого нужен JSON Response. Я бы просто отправлял и получал html текст.
    Удачи!
    --- Добавлено ---
    Согласен с Вами. Сложная идентификация клиента в данном случае не нужна.
    Однако сохранение в сессии не подходит из-за того, что она создаётся на сеанс и имеет ограниченное время жизни.
    Поэтому правильнее использовать Куки.
    --- Добавлено ---
    Уточните, пожалуйста, это:
    "чтобы за одну секунду не могло выводиться 25 анекдотов например одному пользователю при перезагрузка х страницы."
    Каждый анекдот в одну строку?
     
  6. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.787
    Симпатии:
    1.327
    Адрес:
    Лень
    @Survivor $anekdot === false достаточно empty
    --- Добавлено ---
    Юзер зашел с приватной вкладки. Куки пока.
    --- Добавлено ---
    Или лично с инструмента del куку сделал. Ну а если парсить сайт начнут. Тут не сессия, не куки, а нужно запрет на не авторизованных юзеров
     
  7. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    331
    Симпатии:
    66
    Адрес:
    Бавария, Германия
    Вообще-то о авторизации юзеров Евгений Владимирович ничего не писал. Вероятно её и нет вовсе.
    А если не сессия, не куки, то должна быть проверка и должно быть определено, что делать.
    Типа, не показывать анекдоты анонимному юзеру, или, если показывать, то как.
     
  8. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.787
    Симпатии:
    1.327
    Адрес:
    Лень
    я про что писал в своем последнем посту ?
     
  9. Drunkenmunky

    Drunkenmunky Активный пользователь

    С нами с:
    12 авг 2020
    Сообщения:
    1.478
    Симпатии:
    281
    Похоже, что, изначально, автора это и беспокоит. Раз таймаут видит решением.
    Как выше уже предлагали, сессий для этого вполне достаточно.
    Только выдавать нужно не случайный анекдот, а следующий по списку
     
  10. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    331
    Симпатии:
    66
    Адрес:
    Бавария, Германия
    MouseZver,
    Это должно быть определено в постановке задачи.
    Более очевидное в этом случае решение показывать случайный анекдот.
    Между прочим. Что значит запрет? Убирать весь блок анекдотов?
    Придётся мудрить с разметкой.

    Согласен.
    Только сколько потребуется уникальных анекдот для того чтобы делать обновления каждые три секунды?

    P.S. Делал один партийный сайт и там был блок политических анекдотов. Примерно такая же идея была у владельца ресурса.
    Анекдоты закончились на следующий день после запуска сайта.
     
  11. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.787
    Симпатии:
    1.327
    Адрес:
    Лень
    Это выход который я предлагаю, а Автора беспокоит совсем другое.

    Как выше описывал, сессией не достаточно если на нее онли делать показ текст. Еще раз повторю.

    Вообще-то случайный, см. код автора o_O Только добавить немного надо - что тип посмотрел этот текст и нужно другой показать.


    Конечно, только не очевидно, а автор изначально это дал понять.
    Ты сможешь сюда написать пост ну или увидеть свои настройки пользователя, если ты не залоген ? Я хз почему тут возникают какие-либо вопросы.


    ;)

    Пишите ему авторизацию, а не просто на куках/сессиях пилить тайм аут, который благополучно обойду приватной вкладкой.
     
  12. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.084
    Симпатии:
    1.239
    Адрес:
    там-сям
    Ребята, проще надо быть.

    Раз НЕ ставится условие что последовательность выдачи анекдотов должна быть уникальной для каждого пользователя, будем менять выдачу для всех одинаково!

    Пишем функцию которая меняет результат не чаще, чем раз в три секунды (или сколько мы решим).

    PHP:
    1. function lazyTimer(int $interval = 3): int {
    2.   return intval(time() / $interval);
    3. }
    Очевидно результат будет большим целым числом. А нам надо впихнуть его в промежуток 0 .. totalPageNum-1 .
    Это будет "номер страницы":
    PHP:
    1. $page = lazyTimer(3) % $totalPageNum;
    @Евгений Владимирович Используй этот номер чтобы читать определенные строки из своего файла. Детали уже сам додумай...
    с тебя пиво
    --- Добавлено ---
    P.S. Если кому-то кажется, что он прочитал требование что надо идентифицировать пользователя или что надо проверять не читал ли он уже этот случайный анекдот в прошлый раз — перечитайте о чем попросил ТС. Не было такого!
     
    Aleksandr.B нравится это.
  13. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.787
    Симпатии:
    1.327
    Адрес:
    Лень
    Вот тут как раз двух смысловой контекст. Новый анекдот показать и не важно был он показан в предыдущий раз. Новый анекдот считается как новый, не показывая одно и тоже с пред.
    --- Добавлено ---
    Про идентификацию - при хорошем раскладе, она нужна чтобы сейвить тайм, иначе вот это всё что тут разжёвывается - не о чем.
    --- Добавлено ---
    Или можно совсем по иному пути пойти. Делать lock на стороне сервера со значением id или текст анекдота, а потом чекать его просроченность по дате. Любой запрос обновляет значение если тайм разрешает и сейвим для всех пользователей.
     
  14. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    331
    Симпатии:
    66
    Адрес:
    Бавария, Германия
    При любом раскладе потребуется очень много анекдотов.
    Может просто по номерам? например,
     
  15. Евгений Владимирович

    Евгений Владимирович Активный пользователь

    С нами с:
    3 май 2009
    Сообщения:
    28
    Симпатии:
    0
    Анекдотов в базе очень много
    Я их сам так и напарсил с информера анекдотов
    Проверял условие
    И если анекдота нет ещё в базе, то записывать в этот текстовый файл
    И так каждый раз .
    Подключил этот скрипт к странице
    И при посещении сайта пользователями этот скрипт открывал этот информер анекдотов и дальше уже всё по схеме
    Одно посещение - один анекдот писался в базу
    И так со временем, когда база практически перестала расти, я понял что спарсил практически все анекдоты с информера.
    Анекдотов в базе ну очень много. Поэтому не важно, видео он его или нет- снова этот анекдот вряд-ли попадется. Да даже если и попадется. При перезагрузке- новый.
    Я думал как проще и на php без заморочек и сессий. Думаю нужно отдельный текстовый файл и туда писать время запуска. А затем смотреть. Не прошла ли одна секунда. Если секунда прошла- то повторяем цикл рандома из базы. А если нет ещё -то не повторять. И выводить то, что есть снова. Потому что если тысяча человек начнут постоянно тыкать обновить страницу как hamster kombat(https://t.me/hamster_kombat_Bot/start?startapp=kentId1253006722)
    Прошу прощения, но вдруг кто-то не играл.
    Так вот. Это будут миллионы чтений базы в секунду. Поэтому нужна хоть какая-то защита. Простая. Ну я так думал. Если это будет реализовано без сессии на php как я сказал, то такую защиту думаю будет сложно обойти
     
  16. Евгений Владимирович

    Евгений Владимирович Активный пользователь

    С нами с:
    3 май 2009
    Сообщения:
    28
    Симпатии:
    0
    Пишем функцию которая меняет результат не чаще, чем раз в три секунды (или сколько мы решим).
    PHP:
    1. function lazyTimer(int $interval = 3): int {
    2.   return intval(time() / $interval);
    3. }
    Очевидно результат будет большим целым числом. А нам надо впихнуть его в промежуток 0 .. totalPageNum-1 .
    Это будет "номер страницы":
    PHP:
    1. $page = lazyTimer(3) % $totalPageNum;
    немного сложновато это для моего понимания
    в любом случае функция вообще никак не хочет что-то работать
    в любом виде
    даже построчно
    даже с моими переменными. ни без них
    никак
    время делить на интервал
    Получим большое целое число
    и впихиваем его в строки
    что вообще происходит
    ктонибудь пробовал запустить эту задержку? да просто на строках
    строка 1
    строка 2
    строка 3
    и чтобы не менялись какое-то время после одновления. так и оставалась строка 1 например какое-то время
    Эта функция меня напрочь в ступор вводит
     
  17. Aleksandr.B

    Aleksandr.B Новичок

    С нами с:
    2 фев 2023
    Сообщения:
    157
    Симпатии:
    41
    Адрес:
    Барнаул
    Код (Text):
    1. $data = [
    2.     "строка 1",
    3.     "строка 2",
    4.     "строка 3",
    5. ];
    6. function lazyTimer(int $interval = 5): int {
    7.     return intval(time() / $interval);
    8. }
    9.  
    10. $page = lazyTimer(10) % count($data);
    11. echo $data[$page];
     
    artoodetoo нравится это.
  18. Евгений Владимирович

    Евгений Владимирович Активный пользователь

    С нами с:
    3 май 2009
    Сообщения:
    28
    Симпатии:
    0
    а я бился, не получалось
    оказалось, что не работает под php 5.3
    а я тестировал именно на старом сайте
    и ни в какую.
    Теперь вижу что отлично работает
    даже изумительно
    куда скинуть на пиво.
    нужны контакты
    Человек действительно помог
    теперь осталось несколько вопрпосов:
    указывал просто
    $data = file('anekdot.dat');
    но нужно ли открывать сначала через fopen
    а потом закрывать - fclose
    хотя работает и без этого
    и тратится ли процессорное время если тысячи раз постоянно делать fopen fclose
    стало интересно. а если просто указываю как $data = file('anekdot.dat'); он какое-то время сам в памяти висит?
     
  19. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    331
    Симпатии:
    66
    Адрес:
    Бавария, Германия
    fopen и fclose можете убрать, причём в любой версии PHP
    см. https://www.php.net/manual/ru/function.file.php
     
    #19 Vladimir Kheifets, 27 июн 2024
    Последнее редактирование: 27 июн 2024