Конкурс:Дизайн Коридоров
Случайные изображения
|
Как Разбить Вывод Из Mysql Постранично (php)
|
|
|
|
6.9.2009, 7:30
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Как разбить вывод из mysql постранично (php)
Как сделать постраничный вывод из mysql "как в яндексе"? по 10 записей на страницу, внизу - ссылки на остальные страницы?
Сначала научимся получать из базы нужное количество записей. Их получение в mysql обеспечивается оператором LIMIT, который вызывается с двумя параметрами - с какой записи начинать, и сколько выводить (внимание! не по какую, а сколько!) SELECT * FROM table LIMIT 0,10 этот запрос вернет записи с первой по 10, поскольку нумерация начинается с 0 соответственно, запрос для третьей страницы будет выглядеть, как SELECT * FROM table LIMIT 20,10 получается, что нам всего лишь надо передать в скрипт число, которое потом подставить в запрос. Этим будет заниматься код, который выводит ссылки на страницы. Естественно, в цикле. Для цикла нам понадобится количество записей, которое возвращает запрос без лимита.
|
|
|
|
|
|
Ответов
(1 - 6)
|
6.9.2009, 7:35
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Определить количество записей можно получить двумя путями. Либо отдельным запросом, в котором отсутствует оператор LIMIT, а вместо перечисления полей после оператора SELECT запрашивается только count(*): Код $q="SELECT count(*) FROM table"; $res=mysql_query($q); $row=mysql_fetch_row($res); $total_rows=$row[0]; Либо, если версия mysql больше 4.0, то общее количество строк можно запросить в том же запросе. См. документацию mysql по функции FOUND_ROWS() Однако, первый сособ представляется более удобным, хотя и немного более медленным. Вывод ссылок - это простейшая арифметическая операция и никаких особенных знаний для нее не требуется. Для тех, же, кто ищет готовый, простой код, продолжим ниже.
|
|
|
|
|
6.9.2009, 7:39
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Определение количества записей, способ 2Начиная от версии 4.0 в СУБД MySQL появилась достаточно удобная возможность подсчета количества всех подходящих под запрос записей, когда количество записей ограничивается LIMIT’ом. При работе с поиском в БД, а так же при выборках из таблиц с большим количеством записей такой функционал просто необходим. Синтаксис. В запросе SELECT перед списком столбцов необходимо указать опцию SQL_CALC_FOUND_ROWS. Вот начало описания синтаксиса конструкции SELECT. Код SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr, … … Таким образом, выполняя запрос SELECT SQL_CALC_FOUND_ROWS СУБД подсчитает полное число строк, подходящих под условие запроса, и сохранить это число в памяти. Естественно, имеет смысл запрос SELECT SQL_CALC_FOUND_ROWS только при использовании ограничения (LIMIT). Сразу после выполнения запроса на выборку для получения количества записей нужно выполнить еще один SELECT-запрос: SELECT FOUND_ROWS ();. В результате MySQL вернет одну строку с одним полем, в котором и будет храниться число строк. Пример самих запросов: Код > SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE number > 100 LIMIT 10; > SELECT FOUND_ROWS(); Первый запрос вернет (выведет) 10 строк таблицы tbl_name, для которых выполняется условие number > 100. Второй вызов команды SELECT возвратит количество строк, которые возвратила бы первая команда SELECT, если бы она была написана без выражения LIMIT. Хотя при использовании команды SELECT SQL_CALC_FOUND_ROWS, MySQL должен пересчитать все строки в наборе результатов, этот способ все равно быстрее, чем без LIMIT, так как не требуется посылать результат клиенту. Пример запросов из PHP: Код $result = mysql_query(”SELECT SQL_CALC_FOUND_ROWS * FROM table1 LIMIT 0, 10″, $link); while ($row = mysql_fetch_assoc($result)) { var_dump($row); }
$result = mysql_query(”SELECT FOUND_ROWS()”, $link); $num_rows = mysql_result($result, 0); echo “$num_rows Rows\n”; В результате выполнения кода при условии, что $link указывает на открытое соединение с СУБД, PHP выведет 10 строк из таблицы table1 , а затем целочисленное значение количества строк, соответствующих запросу (без учета LIMIT). В запросах с UNION SQL_CALC_FOUND_ROWS может вести себя двояко из-за того, что LIMIT может появляться в нескольких местах. Счет строк может вестись для индивидуальных SELECT-запросов, или же для всего запроса после объединения. Цель SQL_CALC_FOUND_ROWS для UNION состоит в том, что он должен вернуть количество строк, которые будут возвращены без глобального LIMIT. Условия применения SQL_CALC_FOUND_ROWS с UNION перечислены ниже: » Ключевое слово SQL_CALC_FOUND_ROWS должно указываться в первом операторе SELECT. » Значение FOUND_ROWS() будет точным только при условии применения UNION ALL. Если указано UNION без ALL, происходит исключение дубликатов, и значение FOUND_ROWS() будет лишь приблизительным. » Если в UNION не присутствует LIMIT, то SQL_CALC_FOUND_ROWS игнорируется и возвращается количество строк во временной таблице, которая создается для выполнения UNION. SQL_CALC_FOUND_ROWS, SQL_COUNT_FOUND_ROWS, SQL_ FOUND_ROWS
|
|
|
|
|
6.9.2009, 7:44
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Определим сколько всего получится страниц. Для этого надо поделить общее число записей на количество оных на одной странице и округлить результат в большую сторону. Таким округлением занимается в пхп функция ceil() Код $num_pages=ceil($total_rows/$per_page); В этом выражении участвует переменная $per_page, в которую мы положим количество выводимых на странице записей. Ведь, если это количество изменится, мы же не хотим ползать по всему коду и исправлять цифры? проще сделать это один раз в начале скрипта при объявлении переменной. В запрос, вторым параметром LIMIT, подставлять нужно, конечно же, тоже ее.
|
|
|
|
|
6.9.2009, 7:44
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Вывод ссылок. Код for($i=1;$i<=$num_pages;$i++) { echo '<a href="'.$_SERVER['PHP_SELF'].'?num='.$i*$per_page.'">'.$i."</a>\n"; } в цикле от 1 до $num_pages выводим ссылку с параметром num, равным числу, которое надо передать в LIMIT, а в тексте ссылки пишем номер страницы, поскольку людям понятнее видеть номер страницы, а не записи. На код это не влияет, а людям приятно.
|
|
|
|
|
6.9.2009, 7:49
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Пример постраничной разбивки вывод из mysql, и перелистывания (php) Сперва незначительные украшения. Во-первых, некрасиво, что номер страницы не совпадает с тем, что видно в адресной строке. Эту проблему можно решить, передавая по ссылке номер страницы в человекопонятном формате, а в скрипте вычислять первый операнд для LIMIT. Во-вторых, мы явно захотим выделить текущую страницу, не оформляя ее ссылкой. В-третьих, мы захотим нумеровать записи что у нас в результате получилось? Код // количество записей, выводимых на странице $per_page=10; // получаем номер страницы if (isset($_GET['page'])) $page=($_GET['page']-1); else $page=0; // вычисляем первый оператор для LIMIT $start=abs($page*$per_page); // составляем запрос и выводим записи // переменную $start используем, как нумератор записей. $q="SELECT * FROM `table` ORDER BY field LIMIT $start,$per_page"; $res=mysql_query($q); while($row=mysql_fetch_array($res)) { echo ++$start.". ".$row['field']."<br>\n"; }
// дальше выводим ссылки на страницы: $q="SELECT count(*) FROM `table`"; $res=mysql_query($q); $row=mysql_fetch_row($res); $total_rows=$row[0];
$num_pages=ceil($total_rows/$per_page);
for($i=1;$i<=$num_pages;$i++) { if ($i-1 == $page) { echo $i." "; } else { echo '<a href="'.$_SERVER['PHP_SELF'].'?page='.$i.'">'.$i."</a> "; } }
|
|
|
|
|
6.9.2009, 7:53
|
Опытный Пользователь
Группа: Малёк
Сообщений: 241
Регистрация: 20.1.2009
Пользователь №: 14435
|
Пример постраничной разбивки вывод из mysql, и перелистывания (php) Вариант 2. Разумеется, вышеприведённый код подходит только как учебное пособие. С его помощью становится понятным принцип, но в реальных условиях мы сразу же столкнемся, как минимум, с двумя проблемами: Во-первых, кроме переменной $page нашему крипту явно будут переданы и другие переменные, да и адрес может совсем не совпадать с именем скрипта. А мы это при формировании ссылок не учитываем. Во-вторых, нормальный современный сайт немыслим без шаблонов. И такая ужасная лапша из SQL запросов, PHP кода и HTML тегов никуда не годится. Займемся решением этих проблем. Первая решается просто: Код $uri = strtok($_SERVER['REQUEST_URI'],"?")."?"; if (count($_GET)) foreach ($_GET as $k => $v) if ($k != "page") $uri.=urlencode($k)."=".urlencode($v)."&"; и полученную переменную $uri подставляем в код вместо $_SERVER['PHP_SELF'] Вторая - тоже несложно. Шаблонизаторов много, но мы воспользуемся самым универсальным - PHP. Что же у нас получилось? А получился у нас - рефакторинг! Переделка старого кода в соответствии с требованиями современности, плюс мелкое причесывание: Код <? //определим фрагмент запроса, который отвечает за то, какие записи мы запрашиваем $from_where="FROM table WHERE filter=1"; // и получим общее количество записей $res=mysql_query("SELECT count(id) ".$from_where); $row=mysql_fetch_row($res); $total_rows=$row[0];
//дальше получаем номер страницы и значение для лимита if (isset($_GET['page'])) $CUR_PAGE=($_GET['page']); else $CUR_PAGE=1; $start=abs(($CUR_PAGE-1)*$per_page);
//выполняем запрос и получаем данные для вывода $query="SELECT * $from_where ORDER BY date DESC LIMIT $start,$per_page"; $res=mysql_query($query); while ($row=mysql_fetch_array($res)) $DATA[++$start]=$row;
//определяем адрес страницы без переменной page $uri=strtok($_SERVER['REQUEST_URI'],"?")."?"; if (count($_GET)) { foreach ($_GET as $k => $v) { if ($k != "page") $uri.=urlencode($k)."=".urlencode($v)."&"; } } //узнаем общее количество страниц и заполняем массив со ссылками $num_pages=ceil($total_rows/$per_page); for($i=1;$i<=$num_pages;$i++) $PAGES[$i]=$uri.'page='.$i;
//а дальше выводим в шаблоне днные и навигацию: ?> Найдено сообщений: <b><?=$total_rows?></b><br><br> <? foreach ($DATA as $i => $row): ?> <?=$i?>. <a href="?id=<?=$row['id']?>"><?=$row['title'])?></a><br> <? endforeach ?>
<br> Страницы: <? foreach ($PAGES as $i => $link): ?> <? if ($i == $CUR_PAGE): ?> <b><?=$i?></b> <? else: ?> <a href="<?=$link?>"><?=$i?></a> <? endif ?> <? endforeach ?>
|
|
|
|
|
|
|
|