Paging och optimering

Publicerat: 2013-04-29 22:38:20 | Kategori: PHP & SQL

Tro det eller ej, men paging kan vara förbaskat knepigt att få till även på ett mindre projekt. När jag tidigare skrev om att kommentarssystemet var komplext hade jag nog inte riktigt tänkt på paging. Det finns hundratals sätt olika människor har löst det på, det ena klurigare än det andra. Testa bara att googla på simpla paging-skript, det är skrämmande vad folk tycker är enkelt egentligen!

Det som gör det knepigt är egentligen inte att skriptet är långt eller invecklat i sig, men att man måste bädda in det så utomordenligt perfekt i sin egna applikation för att det ska fungera. Det krävs således att man förstår skriptet till punkt och pricka och är det då ett så kallat "enkelt skript" med "endast" 50 rader kod så är det plötsligt en mardröm. Jag hittade till slut en blogg med ett så pass enkelt paging-skript att det faktiskt gick att förstå. Ändå tog det åtskilliga timmar att konvertera php-filen för inlägg.

Här kommer ett exempel på hur sökning fungerade på hraffe.se:

$sql = "SELECT * FROM posts WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%' ORDER BY datum DESC LIMIT 10";

I princip alla databasfunktioner hade ett liknande utseende. När paging kommer in i bilden så blir plötsligt en hel del kod att blanda in i det hela. Utan optimering skulle sökningen plötsligt se ut så här:

$pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%'")));

$sql = "SELECT * FROM posts WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%' ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10";

Utan att överdriva så är det väldigt mycket kod för att endast vara SQL! Med PHP och alla IF/ELSE så blir det fort mycket svårt att hålla reda på. Det jag gjorde var att jag klurade ut ett sätt så strängarna utbyter information. Detta är egentligen inte så avancerat, men absolut ingenting jag tänkte på:

$sql_statement = "WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%'";

 $pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts $sql_statement")));

$sql = "SELECT * FROM posts $sql_statement ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10";

Till synes är det mer kod, men i längden blir det mindre. $sql_statement bestämmer vad SQL-kommandot ska göra och det betyder att man med några IF/ELSE helt enkelt kan bestämma vad som ska visas på sidan. Vi kör med ännu ett exempel på hur sidan skulle se ut utan $sql_statement:

if (isset($_GET['search'])) { 
$pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%'")));

$sql = "SELECT * FROM posts WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%' ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10";

} else if 
(isset($_GET['kategori'])) {
$pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts WHERE kategori LIKE '%$search_kategori%'";

$sql = "SELECT * FROM posts WHERE kategori LIKE '%$search_kategori%'  ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10"; 

} else if (isset($_GET['arkiv'])) {
$pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts  
WHERE DATE_FORMAT(datum, '%M-%Y') = '$search_archive'";

$sql = "S
ELECT * FROM posts WHERE DATE_FORMAT(datum, '%M-%Y') = '$search_archive'  ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10";
}

Det är en enda stor röra som faktiskt går att förenkla enormt även om man inte först tänker på det. Med $sql_statement som jag la till skulle denna röra bli:

if (isset($_GET['search'])) {
$sql_statement = "WHERE rubrik LIKE '%$search_string%' OR kategori LIKE '%$search_string%' OR text LIKE '%$search_string%'";

} else if (isset($_GET['kategori'])) {
$sql_statement = "WHERE kategori LIKE '%$search_kategori%'";

} else if (isset($_GET['arkiv'])) {
$sql_statement = "WHERE DATE_FORMAT(datum, '%M-%Y') = '$search_archive'";
}

$pages = implode(mysqli_fetch_assoc(mysqli_query($GLOBALS["___mysqli_ston"], "SELECT COUNT(id) FROM posts $sql_statement")));

$sql = "SELECT * FROM posts $sql_statement ORDER BY datum DESC LIMIT " . (($page - 1) * 10) . ", 10";

Plötsligt så är koden på hela sidan betydligt förenklad och ger mycket mer överblick! Det är precis såhär man måste tänka när man kodar en hemsida. Jag vet inte hur andra tänker, men själv så har jag tidigare lagt krutet på att optimera PHP-koden och lämnat SQL-strängarna orörda.

Det här är alltså verkligen inte en guide till hur paging fungerar, men hur man ska tänka och hur man ska få det lättare att tillämpa paging. Jag rekommenderar att titta på Aspektas blogg för att hitta koden jag utgick ifrån.


comments powered by Disqus