Странициране на извеждани резултати (1,2,3... последна)

sizif

Registered
Относно статията за странициране на извежданите резултати от БД

Kак ще изглежда извеждането на резултатите, ако става дума за съдържание на текстови файлове, а не за редове в БД?
Приемаме, че всички файлове, които трябва да бъдат визуализирани се съдържат в една директория (.../tc-fajlove). Отваряме я и я четем, после с цикъл имената на файловете се отделят от имената на поддиректориите и постъпват в масив като всеки елемент на масива е име на файл. Обхождаме масива и чрез включване визуализираме съдържанието им.
Кода:

[
Код:
] 
<?
$g=opendir('/home/www/probna.bg/tc-fajlove');
while ($fajl= readdir( $g ) )
{
if(!is_dir($fajl) && !is_link($fajl) && $fajl != ".." && $fajl != ".") {
$fm[]=$fajl;
}
}

closedir ($g);

while (list ($value) = each ($fm)) {
include ("/home/www/probna.bg/tc-fajlove/$value");
}

?>
[
]

Дотук нямам проблем - кода действа, но извежда (включва) всичко на едно място и потребителят ще има да превърта единствената страница до второ пришествие. Чрез стандартния for-цикъл мога да обхождам масива така че да извежда само по 5 резултата, но не мога да обвържа покзаването им с так.нар "странициране"...
Ако не ви затруднявам, можете ли да ми скицирате как мога да направя това или да разясните втората част от поместения в статията код?
Благодаря предварително!

ПП: пуснах въпроса си като коментар към статията, после видях забележката: "за въпроси позлвайте форума" и веднага се поправям. :D
 

Admin

Registered
Най-вероятно има начин това да се получи.
Аз обаче не се наемам да пробвам, защото ще отнеме време.

Кода от урока не може да се преизползва тук.
Нещата са доста различни.

В базата данни има primary key - цяло число, което не се повтаря.
Това е много голямо предимство.

Ако ползваш файл за база данни пак ще е по-лесно, защото ще е подредено някак си ( по редове и колони).

Но от друга стана се сещам за един алгоритъм (простичък).

Завърташ цикъла и ако стане повече от 5 се появява един бутон
"Напред" (примерно) .
Този бутон е примерно линк, който праща $_GET или $_POST данни .
Тези данни са всъщност броя до който си стигнал с цикъла.

Примерно след първото завъртане ще стане test.php?broi=5
и като натисне потрябителя на него ще изпрати, данни broi=5.
Цикъла ще почне от 5 и ще покаже следващите до 10.
Този път линка ще е test.php?broi=10 и т.н.

Надявам се да съм обяснил като хората.:?
 

sizif

Registered
Здравей!
Не съм съгласен, че нещата са доста различни. Не използвам БД, но принципа на работа с нея ми е известен...
В моя случай половината работа вече е свършена - получено е съдържанието на директорията, отделени са файловете, събрани са в масив, а всеки масив е индексиран по някакъв начин.
Масивът fm[] за който става дума е числово индексиран. Всеки елемент има key - ключ, чрез който може да бъде извикан, а тук той е ЦЯЛО, ПОЛОЖИТЕЛНО ЧИСЛО, което НЕ СЕ ПОВТАРЯ. Какво е толкова сложното и различното?!
Според теорията на РНР щом информацията е събрана в масив, нужно е само да бъде обходен той, за да се получи достъп до всеки негов елемент...
Чрез функцията count ($fm); можем да получим броя на елементите, а тъй като не съм указал от колко да започне индексирането му, то key-я на първият елемент е нула, на втория 1 и т.н (най-малкото това съм го получил като данни)...
Идеята, к ми предлагаш не е лоша, но е сурогат. Вече ползвам подобен код при друга хипотеза, но тук наистина се нуждая от странициране. Все пак, благодаря, че си отделил време да върнеш отговор.
Днес разгледах примерния код, който си дал за БД и тази вечер ще се опитам да си го напиша сам. Ако не успея (ако се справя ще пусна кода тук), ще те помоля да ми обясниш съдържанието на променливите, к използваш в примерния вариант, защото част от тях (касаещи извличането на информация от БД) не успях да разчета... Във всички случаи продължавам да смятам, че хипотезите са достатъчно близки, за да може примерния код да бъде приложен и при моя случай...

За онзи, който има желание да помогне, въпросът поставен тук, продължава да стои.
 

nvidia

Registered
Ще стане и с текстови файлове.
Друг е въпроса колко ще са тези файлове.
Ако са 1000 няма да има проблем но за повече не е практично.
Ако смяташ, че трябва да се направи точно с файлове ще се опитам да намеря връзка с кода за странициране .
Наистина е време да се насочиш към ДБ.
Достатъчно си научил за текстовите файлове и не виждам причина да
ги ползваш за ДБ.
 

sizif

Registered
Ето кода, до който стигнах. Мисля, че дублирам фор-цикъла при обхождането на масива (не мога да го вържа с променливите, които "заемам" от примерния код), защото същия код (като принцип) преди ми вадеше 5 имена, но без странициране.

Код:
<?
$g=opendir('/home/www/probna.awardspace.com/tc-fajlove');
while ($fajl= readdir( $g ) )
{
if(!is_dir($fajl) && !is_link($fajl) && $fajl != ".." && $fajl != ".") {
$fm[]=$fajl;
}
}

closedir ($g);


$broinastranica = 5; 
$pageNum = 1;

if(isset($_GET['page'])) 
{ 
$pageNum = $_GET['page']; 
} 

$redove = ($pageNum - 1) * $broinastranica; 
" LIMIT $redove, $broinastranica"; 
// тези два реда не ги разбирам, нито къде влизат в примерния код, нито къде трябва да ги ползвам


$kolko=count ($fm);

for($i = позиция; $i < (Нова позиция + $broinastranica= ???); $i++)
echo $fm[$??? ]; // за този цикъл мисля, че имам някакво дублиране или правя логическа грешка, защото ако позицията ми е 0 - кея на първия елемент..., всъщност възможен ли е подобен запис?!



$maxPage = ceil($kolko/$broinastranica); 

$self = $_SERVER['PHP_SELF']; 
$nomeranastranici = ''; 

for($page = 1; $page <= $maxPage; $page++) 
{ 
if ($page == $pageNum) 
{ 
$nomeranastranici .= " $page "; 
} 
else 
{ 
$nomeranastranici .= " <a href=\"$self?page=$page\">$page</a> "; 
} 
} 

if ($pageNum > 1) 
{ 
$page = $pageNum - 1; 
$predishna = " <a href=\"$self?page=$page\"> [<<] </a> "; 

$parva = " <a href=\"$self?page=1\">[pyrva]</a> "; 
} 
else 
{ 
$predishna = ' '; 
$parva = ' '; 
} 

if ($pageNum < $maxPage) 
{ 
$page = $pageNum + 1; 
$sledvashta = " <a href=\"$self?page=$page\"> [>>] </a> "; 

$posledna = " <a href=\"$self?page=$maxPage\">[posledna]</a> "; 
} 
else 
{ 
$sledvashta = ' '; 
$posledna = ' '; 
} 

 
echo $parva . $predishna . $nomeranastranici . $sledvashta . $posledna; 

?>

Сега страницирането се получава, но то си идва от заетия применер код и обвързването му с целия брой елементи в масива ($kolko). Проблемът е, че не мога да обходя масива така, че да ми дава по пет резултата (а онзи ден някакси ми се получаваше). Снощи имах идея, как да го довърша, но след днешните прибързани напъни се оплетох дотолкова, че честно си признавам, не зная какво правя, даже докато обяснявах в кода още повече се обърках... :shock:

Не мога да премина на база данни тук, защото цялата страница се гради на файлове, вкл действията на админ менюто, което съм направил.

Моля, помогнете!

ПП:
Код:
for($i = 0; $i < $broinastranica; $i++){
echo $fm[$i];
}

Ето това е стария запис на обхождащия цикъл, който вади 5 резултата, но те ен са обвързани със страницирането :(
 

Admin

Registered
sizif . :)
Кода ти работи перфекно.
Тамън си мислех, че ще се наложи да го пиша (а ме мързеше).
Незнам защо си се поколебал да го довършиш.
Трябваше само да нанеса липсващите променливи там където беше оставил питанките.
Имаше и едно $broinastranica= ??? което махнах и това е.

Ето ти демо:
http://www.wthost.net/dir.php

Тези файлове, които се листват в демото са без разширение .
Ако имаха разширение щеше да се вижда.

Кода:

<?
$g=opendir('/home/www/probna.awardspace.com/tc-fajlove/');
while ($fajl= readdir( $g ) )
{
if(!is_dir($fajl) && !is_link($fajl) && $fajl != ".." && $fajl != ".") {
$fm[]=$fajl;
}
}

closedir ($g);


$broinastranica =10;
$pageNum = 1;

if(isset($_GET['page']))
{
$pageNum = $_GET['page'];
}

$redove = ($pageNum - 1) * $broinastranica;
" LIMIT $redove, $broinastranica";



$kolko=count ($fm);

for($i = $pageNum; $i < ($pageNum + $broinastranica); $i++)
echo $fm[$i].'<br/>';



$maxPage = ceil($kolko/$broinastranica);

$self = $_SERVER['PHP_SELF'];
$nomeranastranici = '';

for($page = 1; $page <= $maxPage; $page++)
{
if ($page == $pageNum)
{
$nomeranastranici .= " $page ";
}
else
{
$nomeranastranici .= " <a href=\"$self?page=$page\">$page</a> ";
}
}

if ($pageNum > 1)
{
$page = $pageNum - 1;
$predishna = " <a href=\"$self?page=$page\"> [<<] </a> ";

$parva = " <a href=\"$self?page=1\">[pyrva]</a> ";
}
else
{
$predishna = ' ';
$parva = ' ';
}

if ($pageNum < $maxPage)
{
$page = $pageNum + 1;
$sledvashta = " <a href=\"$self?page=$page\"> [>>] </a> ";

$posledna = " <a href=\"$self?page=$maxPage\">[posledna]</a> ";
}
else
{
$sledvashta = ' ';
$posledna = ' ';
}


echo $parva . $predishna . $nomeranastranici . $sledvashta . $posledna;

?>
 

sizif

Registered
Благодаря ти, admin! Дори си направил демо!

Тази сутрин си мислих, че имам решенито, но когато следобед започнах да пиша прословутия фор-цикъл реших, че греша и от там нататък се оплетох доста... Прегледах завършения код и отбелязаните с червено променливи, които си поставил. Наистина изглежда лесно. Още веднъж, благодаря!

Тъй като на мен страницирането ми е нужно за завършването на раздел за новини (актуализиращ се без да се ползва админ-менюто на сървъра), въпросният код е част от по-голяма система, касаеща работата с файлове. До 2-3 дни се надявам да я завърша и обещавам да поместя тук примерните скриптове. Надявам се, че ще бъдат полезни.

Успешен ден/нощ!
 

Admin

Registered
Поне 10 пъти в този форум се е задавало въпроса
"Как да се листне директория" ама все ме мързеше да напиша някакъв код.
Следващия път просто ще ги пращам към тази тема.

Почвай базите данни.
Не може да се обясни разликата между релационна база данни и
текстови файлове за база данни.
Трябва да я видиш.
 

sizif

Registered
Здравей!

Уви, този код ще се окаже изтощителен. Решили сме проблема само привидно.
Видях кода, стори ми се логичен, но когато го пробвах, резултатът не беше очаквания. Вместо да извежда всеки път по 5 нови резултата (толкова зададох на $broinastranica), кода извежда 4 вече показани + 1 нов.

Реших, че нещо не съм копирал както трябва и за всеки случай проверих за съответствия резултатите, които извежда демото:

Стр 1:

84.54.143.153
84.242.159.2
85.187.23.206
82.103.91.62
84.54.186.35
83.148.88.181
62.204.134.106
212.104.106.11
85.187.137.82
85.255.175.140


стр 2:

84.242.159.2
85.187.23.206
82.103.91.62
84.54.186.35
83.148.88.181
62.204.134.106
212.104.106.11
85.187.137.82
85.255.175.140

85.95.86.167

стр 3:

85.187.23.206
82.103.91.62
84.54.186.35
83.148.88.181
62.204.134.106
212.104.106.11
85.187.137.82
85.255.175.140
85.95.86.167

84.201.201.201

Започнах да човъркам кода "козметично":

Тъй като при мен цикъла не започва от 1 (колкото е началната стойност на $pageNum), промених

for($i = $pageNum; .......

на

for($i = 0; .......

Тогава извеждането започна от първия елемент (с kay=0), но отново продължи да повтаря вече изведени резултати и само един нов. Тъй като сме ограничили броя на възможните страници до толкова, колкото биха били нужни при показване само на нови резултати:

$maxPage = ceil($kolko/$broinastranica);

не могат да се визуализират всички възможни резултати (елементи на масива)

Всъщност, броя на получаваните нови резултати съответстват на текущата стойност на $pageNum, която всеки път се увеличава само с 1. Защо цикълът се завърта 5 пъти (и извежда 5 елемента), но дава само по един нов резултат? Причнита е в това, че позицията за четене при всяко завъртане на цикъла е текущата стойност на $pageNum, която няма как да не изостане от броя на показваните резултати - на всяка нова страница по 5:

for($i = $pageNum; $i < ($pageNum + $broinastranica); $i++)
echo $fm[$i].'<br/>';

Мястото на $pageNum не е в цикъла, обхождащ масива. Или поне не директно. Може би трябва да се въведе нова променлива (да я наречем $start) и да се направи подцикъл (или допълнително условие), в който да се синхронизира движението на $pageNum и $start като се държи сметка за числовата разлика, с която се променя текущата им стойност. Аз се опитах да направя това, но не получих задоволителен резултат :(

Дано съм съумял да обясня правилно проблема. Ако не ти е писнало, моля те, помогни ми да го решим!
 

Admin

Registered
Да.
Нова променлива трябва.
Не видях, че кода не работи щото тези числа вместо файлове ме объркват.
Сега сложих текстови файлове за листване:

<?
$g=opendir('/home/www/probna.awardspace.com/tc-fajlove');
while ($fajl= readdir( $g ) )
{
if(!is_dir($fajl) && !is_link($fajl) && $fajl != ".." && $fajl != ".") {
$fm[]=$fajl;
}
}

closedir ($g);


$broinastranica =10;
$pageNum = 1;

if(isset($_GET['page']))
{
$pageNum =$_GET['page'];
$start = ($pageNum - 1) * $broinastranica;
}




$kolko=count ($fm);

for($i = $start; $i < ($start+$broinastranica); $i++)
echo $fm[$i].'<br/>';



$maxPage = ceil($kolko/$broinastranica);

$self = $_SERVER['PHP_SELF'];
$nomeranastranici = '';

for($page = 1; $page <= $maxPage; $page++)
{
if ($page == $pageNum)
{
$nomeranastranici .= " $page ";
}
else
{
$nomeranastranici .= " <a href=\"$self?page=$page\">$page</a> ";
}
}

if ($pageNum > 1)
{
$page = $pageNum - 1;
$predishna = " <a href=\"$self?page=$page\"> [<<] </a> ";

$parva = " <a href=\"$self?page=1\">[pyrva]</a> ";
}
else
{
$predishna = ' ';
$parva = ' ';
}

if ($pageNum < $maxPage)
{
$page = $pageNum + 1;
$sledvashta = " <a href=\"$self?page=$page\"> [>>] </a> ";

$posledna = " <a href=\"$self?page=$maxPage\">[posledna]</a> ";
}
else
{
$sledvashta = ' ';
$posledna = ' ';
}


echo $parva . $predishna . $nomeranastranici . $sledvashta . $posledna;

?>



Едит:
ПАк бях объркал но сега вече трябва да работи.

Демо
 

sizif

Registered
Благодаря ти за помощта!

Дава малък проблем, но като цяло кода работи отлично.

В началото, когато зарежда основния файл и $page все още няма присвоена стойност цикъла извежда 1 резултат по-малко от зададените. Погледнах демото и там видях същия проблем (9 вместо 10 файла). В моя случай вместо изискваните 5 извежда 4 резултата, но щом въпросната променлива получи някаква стойност ($page=1 , =2 и т.н.) кода се изпълнява според очакванията. Така ако се зареди направо:

..../fail.php?$page=1 ( за стр1),

вместо основния файл:

..../fail.php (който при първо зареджане играе ролята на 1 стр),

грешката може да се заобиколи.

Тествах скрипта в повечето от изчанчените ситуации, които ми хрумнаха и като цяло смятам, че се държи добре. Вече вкарах кода в работния вариант на страницата, която правя. Имам няколко идеи, откъде може да идва разминаването, но в момента бързам да приключа със сайта.
Мисля си, че проблемът може би не е в цикъла (или поне би могъл да се реши без да се човърка в него) - изпълнява се зададения брой пъти, защото отчита 5 нови реда:

echo $fm[$i].'<br/>';

но по някаква причина пропуска да присвои първата стойност на $i... Достраша ме да не объркам синхронизацията при страницирането иначе бих опитал да вкарам някакво допълнително условие за $page, $pageNum и $start... А може и да греша - не съм се опитвал да локализирам точната причина.

Това е засега. Ако някой смята да използва кода, бих го посъветвал да прилага описания по-горе метод за неговото извикване (който с нищо не затруднява работата). Иначе, отново отбелязвам, СТРАНИЦИРАНЕТО РАБОТИ и ако използвате файлове, включването му МОЖЕ ДА ВИ БЪДЕ ПОЛЕЗНО!

До понеделник трябва да завърша пълния код на раздела за новини и както обещах, ще се постарая да публикувам готовите скриптове заедно с обяснения за начина им на действие.

И за финал (тъй като полученият резултат ме удовлетворява): благодаря на всички, които изразиха отношение по въпроса ми!

ПП: ако някой има идея за причината да възниква споменатия проблем, нека се опита да го реши. Страницирането е често използван подход в структурирането на страниците и вярвам, че ако някой успее да прецизира кода, ще окаже помощ на много хора използващи работата с файлове в своите проекти.
 

sizif

Registered
РАБОТИ! :D

БЛАГОДАРЯ ТИ!

ПРОБЛЕМЪТ Е ОКОНЧАТЕЛНО РЕШЕН!
 

cold_zero

Registered
И аз пробвах кода, но има някаква грешка :( В директорията която съм посочил да се индексира има 23 файла, аз съм направил да се показват по 5 файла на страница и по този начин на последната страница трябва да се показват 3 файла, но се показват 5 от които два не съществуват, просто седи на двата файла един X просто да запълнят бройката от 5 файла...Сори за обяснението :?

Код:
<?
$g=opendir('/home/www/probna.awardspace.com/tc-fajlove');
while ($fajl= readdir( $g ) )
{
if(!is_dir($fajl) && !is_link($fajl) && $fajl != ".." && $fajl != ".") {
$fm[]=$fajl;
}
}

closedir ($g);


$broinastranica =10;
$pageNum = 1;

if(isset($_GET['page']))
{
$pageNum =$_GET['page'];
$start = ($pageNum - 1) * $broinastranica;
}
else
{
$start=1;
}




$kolko=count ($fm);

for($i = $start; $i < ($start+$broinastranica); $i++)
echo $fm[$i].'<br/>';



$maxPage = ceil($kolko/$broinastranica);

$self = $_SERVER['PHP_SELF'];
$nomeranastranici = '';

for($page = 1; $page <= $maxPage; $page++)
{
if ($page == $pageNum)
{
$nomeranastranici .= " $page ";
}
else
{
$nomeranastranici .= " <a href=\"$self?page=$page\">$page</a> ";
}
}

if ($pageNum > 1)
{
$page = $pageNum - 1;
$predishna = " <a href=\"$self?page=$page\"> [<<] </a> ";

$parva = " <a href=\"$self?page=1\">[pyrva]</a> ";
}
else
{
$predishna = ' ';
$parva = ' ';
}

if ($pageNum < $maxPage)
{
$page = $pageNum + 1;
$sledvashta = " <a href=\"$self?page=$page\"> [>>] </a> ";

$posledna = " <a href=\"$self?page=$maxPage\">[posledna]</a> ";
}
else
{
$sledvashta = ' ';
$posledna = ' ';
}


echo $parva . $predishna . $nomeranastranici . $sledvashta . $posledna;

?>
 

sizif

Registered
Здравей!
Пиша отговор за 2 мин (толкова имам):
Първо забелязвам, че този фор-цикъл не ти е затворен:

$kolko=count ($fm);

for($i = $start; $i < ($start+$broinastranica); $i++)
echo $fm[$i].'<br/>';


За да решиш проблема, можеш да направиш така:

$kolko=count ($fm);

for($i = $start; $i < ($start+$broinastranica); $i++) {
echo $fm[$i].'<br/>';
if ($i==$kolko) break;
}


Така цикъла ще спре при последния файл, дори да не е завършено основното условие - да изкара 5 имена.

Дано съм помогнал!
Успех!

ПП: вече не ползвам този скрипт, но не е зле да благодаря на Админ, който тогава ми помогна. :)
 

sizif

Registered

Горе