Подгрузка контента при прокрутке (бесконечная лента)

Пример реализации «Бесконечной ленты» с применением PHP, БД MySQL, и JQuery Ajax.

Первый PHP-скрипт выводит только первые 12 записей из таблицы `prods` (записей может быть и больше, главное чтобы высота блока была больше высоты окна браузера).

Ниже, списка товаров выводится
<div id="showmore-triger">, который выполняет роль индикатора загрузки с гифкой ajax-loader.gif и того что пользователь уже доскроллил до этого элемента.

<?php
// Кол-во элементов
$limit = 12; 

// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');

// Получение записей для первой страницы
$sth = $dbh->prepare("SELECT * FROM `prods` LIMIT {$limit}");
$sth->execute();	
$items = $sth->fetchAll(PDO::FETCH_ASSOC);	

// Кол-во страниц 
$sth = $dbh->prepare("SELECT COUNT(`id`) FROM `prods`");
$sth->execute();
$total = $sth->fetch(PDO::FETCH_COLUMN);
$amt = ceil($total / $limit);
?>
	
<div id="showmore-list">
	<div class="prod-list">
		<?php foreach ($items as $row): ?>
		<div class="prod-item">
			<div class="prod-item-img">
				<img src="/images/<?php echo $row['img']; ?>" alt="">	
			</div>
			<div class="prod-item-name">
				<?php echo $row['name']; ?>		
			</div>
		</div>
		<?php endforeach; ?>
	</div>
</div>

<div id="showmore-triger" data-page="1" data-max="<?php echo $amt; ?>">
	<img src="ajax-loader.gif" alt="">
</div>
HTML

CSS-стили:

#showmore-triger {
	text-align: center;
	padding: 10px;
	background: #ffdfdf;
}

/* Вывод товаров */
.prod-list {
	overflow: hidden;
	margin: 0 0 20px 0;
}
.prod-item {
	width: 174px;
	height: 230px;
	float: left;
	border: 1px solid #ddd;
	padding: 20px;
	margin: 0 20px 20px 0;
	text-align: center;
	border-radius: 6px;
}
.prod-item-img {
	width: 100%;
}
.prod-item-name {
	font-size: 13px;
	line-height: 16px;
}

.prod-list .prod-item:nth-child(3n) {
	margin-right: 0
}
CSS

В нём отслеживается скроллинг страницы и в нужный момент отправляется AJAX-запрос на /ajax.php?page=x с номером следующей страницы, который возвращает следующую страницу записей, далее они вставляются в общий список.

При выводе всех страниц из БД, элемент с id="showmore-triger" удаляется методом JQuery remove() – он удаляет элемент из дерева DOM, а также все его JS-события.

<script src="/jquery/2.1.1/jquery.min.js"></script>

<script>
var block_show = false;

function scrollMore(){
	var $target = $('#showmore-triger');
	
	if (block_show) {
		return false;
	}

	var wt = $(window).scrollTop();
	var wh = $(window).height();
	var et = $target.offset().top;
	var eh = $target.outerHeight();
	var dh = $(document).height();   
 
	if (wt + wh >= et || wh + wt == dh || eh + et < wh){
		var page = $target.attr('data-page');	
		page++;
		block_show = true;

		$.ajax({ 
			url: '/ajax.php?page=' + page,  
			dataType: 'html',
			success: function(data){
				$('#showmore-list .prod-list').append(data);
				block_show = false;
			}
		});

		$target.attr('data-page', page);
		if (page ==  $target.attr('data-max')) {
			$target.remove();
		}
	}
}
 
$(window).scroll(function(){
	scrollMore();
});
	
$(document).ready(function(){ 
	scrollMore();
});
</script>
HTML

Скрип получает обрабатывает переменную $_GET['page'] и нужны записи из БД.

<?php
// Кол-во элементов
$limit = 12; 

// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');

// Получение записей для текущей страницы
$page = intval(@$_GET['page']);
$page = (empty($page)) ? 1 : $page;				
$start = ($page != 1) ? $page * $limit - $limit : 0;
$sth = $dbh->prepare("SELECT * FROM `prods` LIMIT {$start}, {$limit}");
$sth->execute();	
$items = $sth->fetchAll(PDO::FETCH_ASSOC);				

foreach ($items as $row) {
	?>
	<div class="prod-item">
		<div class="prod-item-img">
			<img src="/images/<?php echo $row['img']; ?>" alt="">	
		</div>
		<div class="prod-item-name">
			<?php echo $row['name']; ?>		
		</div>
	</div>
	<?php
}
PHP
21.12.2020, обновлено 04.12.2021
21535

Комментарии 4

Алина Хром Алина Хром
11 мая 2021 в 10:36
-3
Подскажите пожалуйста как сделать ленту одним файлом без ajax.php
Александр Устинов Александр Устинов
8 сентября 2021 в 12:15
+1
Зачем? Сторонний файл проще. Однако даже если вам принципиально в один файл - пропишите логику в основном файле, а вывод html в целом сделайте по условию что !isset($_GET['varname']); . Если не знаете как даже такое сделать:
<?php if(!isset($_GET['varname']):?>
<html>
...
</html>
<?php endif;?>
Ну, а далее, делайте аякс на этот же файл.
Владимир Никифоров Владимир Никифоров
23 марта 2022 в 05:02
0
Спасибо за скрипт, а как сделать чтобы данные подгружались не автоматом, а по клику на кнопку "Загрузить еще" ?
Инна Иванова Инна Иванова
11 июня 2022 в 13:21
+1
Ошибка js в консоли при прокрутке до конца ленты: 16381:184 Uncaught TypeError: Cannot read properties of undefined (reading 'top')
at scrollMore (16381:184:27)
at 16381:210:2
at dispatch (jquery.min.js:3:6404)
at r.handle (jquery.min.js:3:3179)

, чтобы добавить комментарий.

Другие публикации

Постраничный вывод и базы данных
В SQL запросах, для ограничения количества строк в результате используется инструкция LIMIT, например следующий вернёт...
9715
+2
Примеры использования PDO MySQL
В статье приведены основные примеры работы с расширением PHP PDO. Такие как подключение к БД, получение, изменение и...
79475
+2
Кнопки прокрутки страницы вверх и вниз jQuery
Несколько примеров как сделать кнопки прокрутки страницы вверх и вниз. Для скроллинга используется jQuery функция...
24415
+3
Появление элементов по очереди
Примеры, как сделать постепенный показ элементов с использованием стандартных функций анимации JQuery.
11963
+2
Модальные окна на Fancybox 3
Fancybox 3 плагин галерей и модельных окон, в отличии от второй версии существенно изменилась скорость работы, дизайн и немного API, далее подробнее о вызове модальных окон.
33346
+3
Загрузка изображений с превью AJAX + PHP + MySQL
В данной статье представлена упрощенная реализация загрузки изображений с превью через AJAX с сохранением в базу данных...
18000
+19