PHP

PHP навигация

Здравствуйте, уважаемые читатели, я постарался максимально проработать скрипт php навигации, и сделать пагинацию на php очень удобной, а самое главное полностью универсальной.

Данный скрипт, в котором будет рассмотрена постраничная навигация php, пригоден для использования, в совершенно любой CMS системе. Достигнуто это благодаря тому, что php навигация реализована выделенным автономным классом, которому для работы нужно лишь получить исходный MySQL запрос, данные для подключения к БД, и параметры вывода.

Когда я только начинал заниматься web программированием, передо мной в скором будущем встала задача реализовать постраничную навигацию. В то время введя в поисковик запросы "пагинация php" и "постраничная навигация php" я был крайне удивлен скудности доступной информации по этой теме.

Сейчас спустя год я задался целью создать такой скрипт php пагинации, который бы можно было использовать абсолютно в любой системе, затратив на это минимум усилий. Должен сказать, что у меня это получилось, и сейчас я хочу продемонстрировать его вам, с подробным описанием его алгоритмов, и способов применения постраничной навигации.

Скрипт постраничной навигации на php
Как я уже упомянул, скрипт реализован автономным классом. Под автономным классом я понимаю, php класс, который можно внедрить в любую систему и при определении экземпляра данного класса, указав любой MySql запрос, а также некоторые настройки, можно сразу получить результат.



На приведенной иллюстрации, изображен результат работы данного скрипта пагинации на php, который выводит на страницу результаты выполненного SQL запроса, и список страниц для навигации.

Как все это работает, я расскажу позже, а пока объясню, как настроить данный скрипт для работы в любой CMS.

Интеграция пагинации в любую CSM



Открыв скачанный архив, вы увидите три файла:

class.navgator.php – включает в себя всю логику генерации страниц и работы с ними.
index.php – его сожержимое показывает как правильно настроить навигацию, и вывести нужную страницу.
style.css – нужен для изменения внешнего отображаемого списка страниц.

Содержимое файла index.php
<link rel="stylesheet" href="style.css" type="text/css" media="screen" /><!--Подключение стилей-->
<?php 
    require_once("class.navigator.php"); // подключение класса для постраничной навигации
    
    $Page=1; //номер страницы которую нужно открыть
    
    if($_GET["page"]) $Page=$_GET["page"]; //если был произведен запрос другой страницы, то присваиваем переменной новый индекс
    
    $array=array(
            array( //настройки для подключения к БД
                'host'=>"localhost", // хост
                'user'=>"root", // пользователь
                'password'=>"", //пароль
                'name_bd'=>"test", //база данных
            ),
            array(      
                'countRecordOnPage'=>5,//количество выводимых записей
                'numberPage'=>$Page,//номер запрашиваемой страницы
                'paramName'=>"page",//название параметры в GET запросе
                'linkCount'=>5, //количество страниц в списке 
                'viewAll'=>false //показать все записи на одной странице        
            )
    );  
    
    $navigator = new Navigator($array, "SELECT * FROM models"); //определяем класс
    echo $navigator->getNavigator();//выводим запрашиваемую страницу
?>

Первым делом подключаем CSS стили и файл с классом навигатора. Затем определяем номер запрашиваемой страницы, через GET параметр, если он существует, иначе будет выведена первая в списке страница.

В массив $array добавляем все необходимые настройки для подключения к базе, а также параметры вывода страницы. Все это передаем в конструктор класса, вместе с запросом. Далее дело техники, и логики работы самого класса навигатора. Единственное, что останется, это вывести сформированную навигатором страницу echo $navigator->getNavigator.

Все требуемые параметры описаны в комментариях файла, так что проблем с пониманием быть не должно. Собственно на этом, те, кто не желает вникать в смысл работы php навигации, могут благополучно пользоваться данным классом. Ну, а интересующимся читателям, я все-таки поведаю, о том, как работает постраничная навигация php.
<?php 
class Navigator{
	//Блок переменных достуных только внутри класса .
	private $SQL_SETTING; // Параметры подключения к БД.
	private $CONNECT; //Указатель на соединение с MySQL.
	private $COUNTRECORD; //Количество выводимых записей на странице.
	private $SQL; // Исходный SQL запрос.
	private $NUMBERPAGE; //Номер текущей страницы.
	private $VIEWALL; //Флаг - показать все страницы. 
	private $PARAMNAME; //Имя параметра в GET запросе например "page".
	private $LINKCOUNT; //количество выводимых ссылок на страницы в пайджере.
	private $NAVIGATOR; //сформировананный навигатор, готовый к выводу.
	// конструктор класса
	public function  __construct($arr,$sql){
		foreach($arr[0] as $attr=>$val){ //Проверяем всели необходимые параметры подключения к БД переданы.
			if(strlen(trim($val))==0 && $attr!='password') return false;// если один из параметров не передан, завершаем работу.
		}
		
		//инициализируем переменные класса
		$this->SQL_SETTING=$arr[0];//Записываем в переменную класса настройки для подключения.
		$this->SQL=$sql;//Записываем в переменную исходный запрос.
		$this->COUNTRECORD=$arr[1]['countRecordOnPage'];//Записываем в переменную класса количество выводимых записей на странице
		$this->NUMBERPAGE=$arr[1]['numberPage'];//Записываем в переменную класса номер текущей страницы.
	    $this->VIEWALL=$arr[1]['viewAll'];//Записываем в переменную флаг "Показать все".
		$this->PARAMNAME=$arr[1]['paramName'];
		$this->LINKCOUNT=$arr[1]['linkCount'];
		//инициализируем соединение с БД
		if($this->initConectionBD()){ //если соединение успешно установленно
			if(!$this->VIEWALL) $this->calcDataPage();// если нет влага "Показать все", вычисляем позицию нужной страницы
			$this->NAVIGATOR=$this->getPage();
			mysql_close($this->CONNECT);
		}
		else return false;
		
		return true;
	} 
	
	public function getNavigator(){
	
		return $this->NAVIGATOR; 
	}

	private function initConectionBD(){
		// если удаоль подключиться к БД
		if($this->CONNECT=@mysql_connect($this->SQL_SETTING['host'],$this->SQL_SETTING['user'],$this->SQL_SETTING['password']))
		{
			//выбираем таблицу для дальнейшей работы
			if(mysql_select_db($this->SQL_SETTING['name_bd'], $this->CONNECT) or die(mysql_error())) return true;
		}
		else{
		 echo "Ошибка подключения к БД!";
		}
			
		return false; //если что - то пошло не так , возвращаем false 
	}
	
	
	private function calcDataPage(){
	
		$result = mysql_query($this->SQL) or die (mysql_error());// выполняем исходный запрос к БД 
		$count=mysql_numrows($result); //узнаем количество возвращенных записей
		$maxCountRecOnPage=ceil($count/$this->COUNTRECORD);//Вычисляем максимально доступное количество страниц
		$this->maxCountRecOnPage=$maxCountRecOnPage;
		if($maxCountRecOnPage<=($this->NUMBERPAGE-1)){ // если максимальное количество страниц меньше чем номер запрашиваемой			$pos=$maxCountRecOnPage-1;
				$pos=$maxCountRecOnPage-1; // то запросим у MySql последнюю доступную страницу
			}	
		elseif(0>=($this->NUMBERPAGE-1)){ //если номер запрашиваемой страницы, меньше либо равен 0
					$pos=0; //то запросим у MySql первую доступную страницу
				}		
			else{ // если запрашиваемая страница попадает в диапазон существующих
					$pos=$this->NUMBERPAGE-1; //то запросим у MySql нужную страницу
				}	
		
		// к запросу дописываем параметр вывода записей с нужной позиции, и их количесвто
		
		
		$this->SQL=$this->SQL." LIMIT ".$pos*$this->COUNTRECORD.", ".$this->COUNTRECORD;
		echo $this->SQL;
	}
	
	//получаем страницу, и выводим ее
	private function getPage(){
		$result = mysql_query($this->SQL) or die (mysql_error());// выполняем запрос к БД		
		$table = "<table border='1'>";	// начинаем формировать таблицу, для вывода полученных данных
		if($row = mysql_fetch_assoc($result)){// получаем первую строку данных		
		$table .= "<tr>";		
		foreach(array_keys($row)as $theader){ // для каждого поля создаем заголовок в таблице
			$table .= "<th>".$theader."</th>";
		}		
		$table .= "</tr>";		
		$table .= "<tr>";			
		foreach($row as $data){//также добавляем полученную строку данных в соответствующие поля таблицы 
		$table .= "<td>".$data."</td>";
		}
		$table .= "</tr>";			
		}
		while ($row = mysql_fetch_assoc($result)){//все оставшиеся строки, добавляем в таблицу 
			
			$odd++%2==0? $odd_class="odd":$odd_class=""; 
			$table .= "<tr class='".$odd_class."'>";			
			foreach($row as $data){
				$table .= "<td>".$data."</td>";
			}		
			$table .= "</tr>";
		}		
		$table .= "</table> ";		
		$page .= $table;
		if(!$this->VIEWALL) $page .= $this->createNavigator();
		
		return $page;
	}
	
	
	private function createNavigator(){
		//формирование  навигатора		
		//если текущая страница, выходит за рамки допустимых, то показываем первую доступную с нужной стороны.
		if($this->NUMBERPAGE<=0)$this->NUMBERPAGE=1; // если текущая страница меньше первой то показываем всегда перву.
		if($this->NUMBERPAGE>$this->maxCountRecOnPage)$this->NUMBERPAGE=$this->maxCountRecOnPage;// если текущая страница больше последней то показываем всегда последнюю.
		
		//создаем кнопки для навигатора
		if($this->NUMBERPAGE>1){ // если не первая страница
		$prev="<a class='nav_button' href='?".$this->PARAMNAME."=".($this->NUMBERPAGE-1)."'><</a>";// создаем сслыку на предыдущую
		$first="<a class='nav_button' href='?".$this->PARAMNAME."=1'><<</a>";	// создаем сслыку на первую
		}
		if($this->NUMBERPAGE<$this->maxCountRecOnPage){ // если не последняя страница
		$next="<a class='nav_button' href='?".$this->PARAMNAME."=".($this->NUMBERPAGE+1)."'>></a>";// создаем сслыку на следующую
		$last="<a class='nav_button' href='?".$this->PARAMNAME."=".$this->maxCountRecOnPage."'>>></a>";// создаем сслыку на последнюю
		}
		
		//средняя часть навигатора , вывод ссылок по половине от общего числа выводимых, по обе стороны текущей страницы
			for($i=($this->NUMBERPAGE-floor($this->LINKCOUNT/2)); $i<=($this->NUMBERPAGE+floor($this->LINKCOUNT/2)); $i++){
				$class="linkPage"; //всем ссылкам назначается класс
				if($i==$this->NUMBERPAGE)$class="activ"; //если ссылка идет на текущую то ей присваивается особый класс
				if($i<=0){ // формирование ссылок на добавочные с конца страницы 				
				$lastpages="<a class='".$class."' href='?".$this->PARAMNAME."=".(abs($i)+$this->NUMBERPAGE+floor($this->LINKCOUNT/2)+1)."'>".(abs($i)+$this->NUMBERPAGE+floor($this->LINKCOUNT/2)+1)."</a>".$lastpages;
				$leftpoint=""; //если начали добавлять  страницы, убираем точки с другого конца
				$noleftpoint=true;// флаг о том что точки слева убраны			
				}
				if($i>$this->maxCountRecOnPage){ // формирование ссылок на добавочные с начала страницы 
				$firstpages="<a class='".$class."' href='?".$this->PARAMNAME."=".abs($i-$this->maxCountRecOnPage-$this->NUMBERPAGE+floor($this->LINKCOUNT/2))."'>".abs($i-$this->maxCountRecOnPage-$this->NUMBERPAGE+floor($this->LINKCOUNT/2))."</a>".$firstpages;
				$norightpoint=true;//если начали добавлять  страницы, убираем точки с другого конца
				$rightpoint="";// флаг о том что точки справа убраны
				}
			
				if($i>0 && $i<=$this->maxCountRecOnPage){ //если формируемая ссылка попадает в интервал допустимых страниц 
				if(!$noleftpoint)$leftpoint="<span class='point'>...</span>"; //добавляем точки слева от списка
				$pager.="<a class='".$class."' href='?".$this->PARAMNAME."=".$i."'>".$i."</a>";//создаем ссылку
				if(!$norightpoint)$rightpoint="<span class='point'>...</span>"; //добавляем точки справа от списка
				}
			}
		//склеиваем все сгенерированные части навигатора
		$navigator=$first.$prev.$leftpoint.$firstpages.$pager.$lastpages.$rightpoint.$next.$last;
		// возвращаем полученный список страниц
		return $navigator;
	}
}

В классе Navigator заведены поля описывающие все необходимые для работы параметры, такие как настройки БД, количество выводимых записей, номер текущей страницы, количество выводимых ссылок на следующие страницы , ну некоторые другие важные и не очень параметры.

В конструкторе класса инициализируются все поля класса, и устанавливается подключение с БД средствами функции initConectionBD(). Затем методом calcDataPage() производится расчет общего количества записей полученных по переданному SQL запросу.

Вычислив количество записей, алгоритм рассчитывает общее число страниц, учитывая параметр $COUNTRECORD, и модернизирует исходный SQL запрос соответствующим параметром LIMIT.

Наверное, надо было раньше рассказать про LIMIT, поскольку вся php навигация построена именно на этом SQL операторе.
LIMIT [offset],[rows]

Ключевое слово LIMIT дописанное в конец любого запроса сообщает MySQL о выводе только [rows] запросов начиная с позиции
.

Конечной целью метода calcDataPage(), нашего класса , в конечном итоге стоит определение необходимых параметров [offset] и [rows], соответствующих запрошенной странице.

Например, для того чтобы из 300 записей, вывести 3-ю страницу и 100 строк на ней, параметры offset и rows должны иметь следующие значения:
[PHP]offset =200
rows = 100

Тогда как для первой:
offset =0
rows = 100

А для второй:
offset =100
rows = 100

В функции calcDataPage() параметры offset и rows вычисляются математически, и к исходному SQL запросу добавляется столь важный оператор LIMIT.

После этого методом getPage(), для последующего выводу формируется таблица из соответствующих запрашиваемой таблице записей. Если вам понадобится вывести данные не в виде таблицы, а другом формате, то придется изменить код этой функции.

PHP пагинация
Осталось вывести лишь средство для постраничной навигации, но для начала нужно сгенерировать список ссылок на соседние страницы от запрашиваемой.

Обратите внимание, список страниц будет меняться в зависимости от положения выбранной страницы относительно остальных в списке.

Всего может быть 5 разных вариантов:



Как видите, отличаются они наличием кнопок навигации и многоточием, означающим, что с соответствующей стороны еще имеется, хотя бы одна доступная страница.

Как реализован данный алгоритм, вы можете посмотреть непосредственно в коде метода, или спросите в комментариях, если будут вопросы.

Завершающим этапом работы конструктора класса Navigator, мы закрываем открытое соединение с базой. Теперь все необходимые данные имеются в полях экземпляра данного класса, и для вывода сгенерированной странце и списка постраничной навигации, нужно лишь обратиться к открытой функции getNavigator().

Обратите ваше внимание на то, что в данном классе доступными из вне, являются только две функции: getNavigator() и __construct().

Такой подход, позволяет ярко выразить заявленную автономность класса php навигации, и исключить возможные ошибки в случае интеграции кода в любую CMS.

Хочу верить в то, что данный материал, послужит вам хорошим подспорьем в решении вопроса постраничной навигации, и вы сможете использовать пагинацию, везде где может понадобиться php навигация.
Теги:
навигация
Добавлено: 28 Сентября 2013 10:49:26 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...