Есть простой скрипт Выводящий анекдот из файла Подключается через 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; ?>
1. Чтоб однозначно определить - тот же это пользователь или нет, нужно применять регистрацию, авторизацию. Если для неавторизованнвх хотите - та еще заморочка.... нужно цифровой слепок барузера делать через js, еще можно к ip привязываться 2. Нужно где-то хранить счетчик показа анекдотов для конкретного пользователя - или записывать в файл или лучше в БД. Записываете время просмотра для каждого просмотра. При записи, предварительно удаляете те элементы - которые уже не укладываются в ваш временной интервал 3. Перед выводом анекдота - смотрите кол-во записей о просмотре данным пользователем - смотрите - все ли они укладываются в аш промежуток - и только если так - показываете вот так ... такая вроде-бы простая формулировка задачи - влечет нехилые затраты. Подумайте - а оно вообще вам надо? Ну посмотрит 40 анекдотов - жалко чтоли? )))
Если прям не упарываться, вряд ли ты банкир, желающий рассмешить своих клиентов. Этого может быть вполне достаточно. anekdot.php PHP: <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Анекдоты</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <style> #anekdot-container { font-size: 20px; margin: 20px; } </style> </head> <body> <div id="anekdot-container">Загрузка анекдота...</div> <script> function show_anekdot() { $.ajax({ url: 'ajax_anekdot.php', type: 'POST', dataType: 'json', success: function( data ) { if (data.error) { return $('#anekdot-container').text(data.error); } if ( data.anekdot ) { $('#anekdot-container').html("<div>" + data.anekdot + "</div>"); //- можно использовать append } }, error: function() { $('#anekdot-container').text('Ошибка при загрузке анекдота.'); } }); } // Отображение первого анекдота сразу после загрузки страницы show_anekdot(); // Показываем новый анекдот каждые 10 секунд setInterval(show_anekdot, 10000); </script> </body> </html> ajax_anekdot PHP: <?php declare(strict_types = 1); error_reporting(-1); header('Content-Type: application/json'); if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { $anekdot = file('anekdot.dat', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // Проверка на наличие анекдотов if ( $anekdot === false || empty( $anekdot ) ) { exit( json_encode(['error' => 'Не с чего ржать']) ); } // Возвращаем анекдот в формате JSON exit ( json_encode(['anekdot' => $anekdot[array_rand($anekdot)]]) ); } Файл с анекдотами Код (Text): Анекдот 1 Анекдот 2 Анекдот 3 Ну, а если прям хочешь защититься: - Проверяй заголовки $_SERVER['HTTP_ORIGIN'] - Создай какой-нибудь ключик api и проверяй его в ajax файле - Если регистрации нет, можно json файлик с сохранением IP юзера (+ чего угодно ещё) и ограничением кол-ва запросов либо pid файлик и ограничивать вообще всех))
Зачем такие сложности? Всё можно в сессии хранить. В начале скрипта session_start(), и хранить в сессии ассоциативный массив, например "номер анекдота" => timestamp показа. И при показе соответственно учитывать информацию из этого массива
Добрый день! Вы отправляете по ajax-запросу только одну строку из файла $anekdot PHP: exit ( json_encode(['anekdot' => [array_rand($anekdot)]]) ); Не понятно зачем для этого нужен JSON Response. Я бы просто отправлял и получал html текст. Удачи! --- Добавлено --- Согласен с Вами. Сложная идентификация клиента в данном случае не нужна. Однако сохранение в сессии не подходит из-за того, что она создаётся на сеанс и имеет ограниченное время жизни. Поэтому правильнее использовать Куки. --- Добавлено --- Уточните, пожалуйста, это: "чтобы за одну секунду не могло выводиться 25 анекдотов например одному пользователю при перезагрузка х страницы." Каждый анекдот в одну строку?
@Survivor $anekdot === false достаточно empty --- Добавлено --- Юзер зашел с приватной вкладки. Куки пока. --- Добавлено --- Или лично с инструмента del куку сделал. Ну а если парсить сайт начнут. Тут не сессия, не куки, а нужно запрет на не авторизованных юзеров
Вообще-то о авторизации юзеров Евгений Владимирович ничего не писал. Вероятно её и нет вовсе. А если не сессия, не куки, то должна быть проверка и должно быть определено, что делать. Типа, не показывать анекдоты анонимному юзеру, или, если показывать, то как.
Похоже, что, изначально, автора это и беспокоит. Раз таймаут видит решением. Как выше уже предлагали, сессий для этого вполне достаточно. Только выдавать нужно не случайный анекдот, а следующий по списку
MouseZver, Это должно быть определено в постановке задачи. Более очевидное в этом случае решение показывать случайный анекдот. Между прочим. Что значит запрет? Убирать весь блок анекдотов? Придётся мудрить с разметкой. Согласен. Только сколько потребуется уникальных анекдот для того чтобы делать обновления каждые три секунды? P.S. Делал один партийный сайт и там был блок политических анекдотов. Примерно такая же идея была у владельца ресурса. Анекдоты закончились на следующий день после запуска сайта.
Это выход который я предлагаю, а Автора беспокоит совсем другое. Как выше описывал, сессией не достаточно если на нее онли делать показ текст. Еще раз повторю. Вообще-то случайный, см. код автора Только добавить немного надо - что тип посмотрел этот текст и нужно другой показать. Конечно, только не очевидно, а автор изначально это дал понять. Ты сможешь сюда написать пост ну или увидеть свои настройки пользователя, если ты не залоген ? Я хз почему тут возникают какие-либо вопросы. Спойлер: Согласен на что ? Пишите ему авторизацию, а не просто на куках/сессиях пилить тайм аут, который благополучно обойду приватной вкладкой.
Ребята, проще надо быть. Раз НЕ ставится условие что последовательность выдачи анекдотов должна быть уникальной для каждого пользователя, будем менять выдачу для всех одинаково! Пишем функцию которая меняет результат не чаще, чем раз в три секунды (или сколько мы решим). PHP: function lazyTimer(int $interval = 3): int { return intval(time() / $interval); } Очевидно результат будет большим целым числом. А нам надо впихнуть его в промежуток 0 .. totalPageNum-1 . Это будет "номер страницы": PHP: $page = lazyTimer(3) % $totalPageNum; @Евгений Владимирович Используй этот номер чтобы читать определенные строки из своего файла. Детали уже сам додумай... с тебя пиво --- Добавлено --- P.S. Если кому-то кажется, что он прочитал требование что надо идентифицировать пользователя или что надо проверять не читал ли он уже этот случайный анекдот в прошлый раз — перечитайте о чем попросил ТС. Не было такого!
Вот тут как раз двух смысловой контекст. Новый анекдот показать и не важно был он показан в предыдущий раз. Новый анекдот считается как новый, не показывая одно и тоже с пред. --- Добавлено --- Про идентификацию - при хорошем раскладе, она нужна чтобы сейвить тайм, иначе вот это всё что тут разжёвывается - не о чем. --- Добавлено --- Или можно совсем по иному пути пойти. Делать lock на стороне сервера со значением id или текст анекдота, а потом чекать его просроченность по дате. Любой запрос обновляет значение если тайм разрешает и сейвим для всех пользователей.
Анекдотов в базе очень много Я их сам так и напарсил с информера анекдотов Проверял условие И если анекдота нет ещё в базе, то записывать в этот текстовый файл И так каждый раз . Подключил этот скрипт к странице И при посещении сайта пользователями этот скрипт открывал этот информер анекдотов и дальше уже всё по схеме Одно посещение - один анекдот писался в базу И так со временем, когда база практически перестала расти, я понял что спарсил практически все анекдоты с информера. Анекдотов в базе ну очень много. Поэтому не важно, видео он его или нет- снова этот анекдот вряд-ли попадется. Да даже если и попадется. При перезагрузке- новый. Я думал как проще и на php без заморочек и сессий. Думаю нужно отдельный текстовый файл и туда писать время запуска. А затем смотреть. Не прошла ли одна секунда. Если секунда прошла- то повторяем цикл рандома из базы. А если нет ещё -то не повторять. И выводить то, что есть снова. Потому что если тысяча человек начнут постоянно тыкать обновить страницу как hamster kombat(https://t.me/hamster_kombat_Bot/start?startapp=kentId1253006722) Прошу прощения, но вдруг кто-то не играл. Так вот. Это будут миллионы чтений базы в секунду. Поэтому нужна хоть какая-то защита. Простая. Ну я так думал. Если это будет реализовано без сессии на php как я сказал, то такую защиту думаю будет сложно обойти
Пишем функцию которая меняет результат не чаще, чем раз в три секунды (или сколько мы решим). PHP: function lazyTimer(int $interval = 3): int { return intval(time() / $interval); } Очевидно результат будет большим целым числом. А нам надо впихнуть его в промежуток 0 .. totalPageNum-1 . Это будет "номер страницы": PHP: $page = lazyTimer(3) % $totalPageNum; немного сложновато это для моего понимания в любом случае функция вообще никак не хочет что-то работать в любом виде даже построчно даже с моими переменными. ни без них никак время делить на интервал Получим большое целое число и впихиваем его в строки что вообще происходит ктонибудь пробовал запустить эту задержку? да просто на строках строка 1 строка 2 строка 3 и чтобы не менялись какое-то время после одновления. так и оставалась строка 1 например какое-то время Эта функция меня напрочь в ступор вводит
Код (Text): $data = [ "строка 1", "строка 2", "строка 3", ]; function lazyTimer(int $interval = 5): int { return intval(time() / $interval); } $page = lazyTimer(10) % count($data); echo $data[$page];
а я бился, не получалось оказалось, что не работает под php 5.3 а я тестировал именно на старом сайте и ни в какую. Теперь вижу что отлично работает даже изумительно куда скинуть на пиво. нужны контакты Человек действительно помог теперь осталось несколько вопрпосов: указывал просто $data = file('anekdot.dat'); но нужно ли открывать сначала через fopen а потом закрывать - fclose хотя работает и без этого и тратится ли процессорное время если тысячи раз постоянно делать fopen fclose стало интересно. а если просто указываю как $data = file('anekdot.dat'); он какое-то время сам в памяти висит?
fopen и fclose можете убрать, причём в любой версии PHP см. https://www.php.net/manual/ru/function.file.php