Разделение на страници

rash

Guest
Разделение на страници

Добрый день!
Мне нужно разделить на страници информацию выведенную из DB.
Т.Е. вывести первые 10 записей, кликнув на ссылку, показать от 10 до 20 записи.
 

rash

Guest
Спасибо!
Но чето я там нифига не понял! :((
 

Bred Vilchec

Новичок
Блин же, там и так все на пальцах объяснено, что называется "для самых маленьких".
"Перечитывай до наступления просветления. Но не более недели" © Crazy
 

Sherman

Mephi
могу дать такой код, пользую его очень давно:

Код:
<?
class Pager  
   {  
       function getPagerData($numHits, $limit, $page)  
       {  
           $numHits  = (int) $numHits;  
           $limit    = max((int) $limit, 1);  
           $page     = (int) $page;  
           $numPages = ceil($numHits / $limit);  

           $page = max($page, 1);  
           $page = min($page, $numPages);  

           $offset = ($page - 1) * $limit;  

           $ret = new stdClass;  

           $ret->offset   = $offset;  
           $ret->limit    = $limit;  
           $ret->numPages = $numPages;  
           $ret->page     = $page;  

           return $ret;  
       }  
   }  
?>
Достаточно написать к нему модуль, это уже зависит от твоей системы.

Код:
$pager  = Pager::getPagerData(params);
на выходе будешь иметь:

Код:
 $pager ->numPages;  
 $pager ->page;
 и т.д.
Оперируя этими переменными и опираясь на логику рендеринга твоего пейджера — получаешь результат.

Плюсы:

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

ООП подход.

Отделение кода от представления.
 

Bred Vilchec

Новичок
Ну а что же такое stdClass и откуда он берется??
А, может это в нем сосредоточены все прелести ООП подхода данного движка? А то что-то я в приведенном коде вижу тока одну функцию, обернутую непонятно зачем в класс.
ИМХО, разделение на страницы - совсем не та задача чтобы решать её методами ООП, здесь достаточно несолькоих строк кода, ссылку на лучший вариант я давал вверху.
 

Bred Vilchec

Новичок
Frol
Ок, спасибо, сходил, прочитал.:)
Однако же смысл его использования в данном случае все равно остается для меня загадкой. Наверное, это специально, чтоб такие ламеры как я не догадались%)
 

Sherman

Mephi
Да дело не в этом, просто в php4 нету привычных средств для создания статичных полей и методов класса.

Никто не мешает тебе сделать так:

Код:
class Pager
{
   var $field1;
   var $field2;
   function Pager($field1, $field2)
   {
      $this->field1 = $field1;
      $this->field2 = $field2;
      $this->Calculate();
   }
   function Calulate()
   {
      //make sonething with fileds
   }
}

$pgrObj = new Pager(5, 1);
$pgrObj->field1;
$pgrObj->field2;
В данном случае это вопрос привычки.
 

Sherman

Mephi
Допустим у меня есть некий модуль, который использует этот класс.
В свою очередь этот модуль содежрит код логики рендеринга пейджера(у меня он аля google), но самого дизайна там нету. Он работает с шаблонами(в моем случае это HTML-шаблоны).

Что мы имеем? А имеем мы трехзвенку.

1 уровень данных(это собственно класс), на этом уровне ничего не известно не о выводе данных, ни о логике вывода, код занимается только самими данными(этот пример не очень удачный, обычно такие классы у меня инкапсулируют еще и всю работу с бд).

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

3 уровень представления, здесь у нас будет просто html-шаблон, котоырй при желании легко меняется на xml/xslt, например. При этом нужно будет сделать минимальные изменения на втором уровне, а первого уровня это вообще никак не коснется.

Ну вот примерно так.

У меня есть класс новостей(публикаций). Работает по той же системе.

Есть разные представляения новостей: html, xml(rss), текстовый файл и вообще может быть, что угодно, но при этом я уже не затрагиваю сам класс новостей, я лишь создаю экземпляр и вызываю нужный метод, в ответ получаю данные, которые мне нужны.

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

И это не CMS. Т.к. я заранее не делаю представление. У меня есть набор классов, есть административный интерфейс, есть несколько типовых модулей.

Создание нового сайта начинается с того, что я делаю новые шаблоны и создаю новые модули представления, при этом почти никогда не меняя сами классы.

p.s. замечу, что я работаю с очень старой версией mysql 3.23.58, а так можно было бы переложить значительную часть логики работы с данными на плечи СУБД.
 

Фанат

oncle terrible
Команда форума
нельзя ли привести пример?
постраничного вывода, реализующего такой плюс Вашего кода, как, цитирую: Отделение кода от представления.
ближе к жизни, так сказать.

заранее спасибо
 

Sherman

Mephi
пример(модуль, типа repeater — абстрактный), идея я думаю понятна, свой код полностью приводить нестану(в частности, модуль постраничного вывода, ибо © :) ):

Код:
class Data
{
   var $data = array("id"=>0,"title"=>"");
   var $dataCollection = array();

   function EnumerateData($condition)
   {
      //get data from database and fill collection
   }
}

Код:
//repeater
require_once "myDataClass.inc"

$dataObj = new Data()
$dataObj->EnumerateData();

if (!empty($dataObj->dataCollection))
{
   $listTpl = new Template("list.tpl");
   foreach($dataObj->dataCollection as $dataItem)
   {
      $listItemTpl = $listTpl->fetchBlock("list_item");
      $listItemTpl->assign("title", $dataItem["title"]);
      $listTpl->assign("list_item",$listItemTpl):
      $listTpl->reset();
   }
    $listTpl->out();
}
Код:
//list.tpl
<table>
<!-- BEGIN list_item -->
  <tr>
    <td>
      {title}
    </td>
  </tr>
<!-- END list_item -->
</table>
Если, например нужно поменять формат, то можно переделать наш модуль или сделать новый, но при этом уровень данных(class Data) остается без изменений.
 

Фанат

oncle terrible
Команда форума
абстрактный код меня не интересует
меня интересовал конкретный код по теме, куда вы, уважаемый, влезли со своими ценними теоретическими построениями.

можно не приводить весь код.
можно привести код вывода номеров страниц со ссылками.
Я надеюсь, постраничный вывод - не такая безумно сложная задача, чтобы защищать ей копирайтами?

если вы не готовы привети здесь код, то я попрошу вас подчистить свои сообщения, как полный оффтопик.
 

Sherman

Mephi
ну какая разница, возбми сделай шаблон, типа:

<table>
<tr>
<!-- BEGIN page_number -->
<td>
{num}
</td>
<!-- END page_number -->
<!-- BEGIN current_page_number -->
<td>
{num}
</td>
<!-- END current_page_number -->
</tr>
</table>

Логику рендеринга кидаешь в модуль, и распирсиваешь шаблон, все данные у тебя для этого уже есть(из класса), а именно:

1. общее кол-во страниц.
2. кол-во элементов на страницу.
3. текущая страница.
 

duke333

Новичок
вопрос такого полана
при получении данных из Базы мы получили 1000 записей нужно выводить постранично 100 записей на страныце
вопрос1: в этом случае лучше воспользоватся вариантом
a) получайм после запроса все данные с Базы , определяем в зависимости от страницы какие данные выволить и в цыкле FOR перебезая все записи отбераем те что нам нужны
б) выполняем запроса COUNT() - для определения обсчего числа записей, определяем в зависимости от страницы смесчение, выполняем запрос на получение данных с использованием LIMIT N*100, N*100+100 где N - номер страницы.

вопрос2: до какого числа записей имеет смысл пользоватся методом а) и до какого методом б) (напирмер если будет 100000000 записей не дума что перебирать их по цыклу будет привильно)
 

Lakr

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

Средняя скорость подсчёта обоих вариантов при 10 записях одинаковое около 0.0004
при 100 записях мускл 0,00049 цыкл 0,00062
при 1000 записях мускл 0,00096 цыкл 0,0029
при 10000 записях мускл 0,0058 цыкл 0,026
и наконец
при 100000 записях мускл 0,054 цыкл 0,26
конечно все цифры субъективны зависят от множества факторов но для наглядности тенденция прослеживается.
 

duke333

Новичок
спасибо за эксперимент, НО
нужно не забывать что при использовании COUNT() в лубом случае придется делать 2 запроса - 1-й определение обсчего количества записей и 2-й непосредственно получение данных в зависимости от страницы.
 

Avron2

Новичок
PHP:
// ==============Рисуем страницы в виде ссылок (напр. 1-10 11-20)===============
Function Pages($records,$r_start,$URL,$inpage)	{
    $str="";                                          //  * $records - всего записей
													  //  * $r_start - текущая страница
													  //  * $URL - адрес, заканчивающийся на "="
													  //  * $inpage - записей на страницу

    if ($records<=$inpage) return; //если всего записей меньше чем на 1-ой странице
    $str.="Страницы &nbsp;";
    if ($r_start!=0) {
        $str.="<a href=".$URL."0>&lt;&lt</a> ";
        $str.="<a href=$URL".($r_start-1).">&lt;</a> ";
        }
    else $str.="&lt;&lt &lt; ";

    if ($r_start==0) {$sstart=$r_start-0;$send=$r_start+10;}
    if ($r_start==1) {$sstart=$r_start-1;$send=$r_start+9;}
    if ($r_start==2) {$sstart=$r_start-2;$send=$r_start+8;}
    if ($r_start==3) {$sstart=$r_start-3;$send=$r_start+7;}
    if ($r_start==4) {$sstart=$r_start-4;$send=$r_start+6;}
    if ($r_start>=5) {$sstart=$r_start-5;$send=$r_start+5;}

    if ($send*$inpage>$records) $send=$records/$inpage;
    if ($sstart<0) $sstart=0;

    if ($records%$inpage==0) $add=0; else $add=1;

    for ($i=$sstart;$i<$send;$i++) {
        if ($i==$r_start) $str.=" <B>".($i+1)."</B> | ";
        else $str.="<a href=$URL".($i)."><U><B>".($i+1)."</B></U></a> |  ";
        }

    if ($r_start+(1-$add)<intval($records/$inpage)) {
        $str.=" <a href=$URL".($r_start+1).">&gt;</a>";
        $str.=" <a href=$URL".(intval($records/$inpage)-(1-$add)).">&gt;&gt;</a>";
        }
    else $str.=" &gt; &gt;&gt";
    return("<table width=100%><tr><td valign=center align=right>".$str."</td></tr></table>");
    }

// Пример вызова
//print "<center>".LeftRight(567,43,"index.htm?start=",20)."</center>";
//=============================================================================
 
Сверху