Autor Zpráva
Lucyk
Profil
Ahoj,

prosím zkušenější o kontrolu následujícího cyklu, který by měl vypisovat po 4 výsledcích na řádku.

echo "<table id='tabulka_vypis'>"; 
echo "<tr>"; 
$poradi = 0;
while (list($rok,$vyrobce,$sada) = mysql_fetch_row($navrat)): 
echo "<td width=\"280\"><a href=\"index.php?rok=$rok&vyrobce=$vyrobce&sada=$sada\"></a></td>"; 
$poradi++;
if($poradi == 4) { 
      echo "</tr><tr>"; 
      $poradi = 0; 
}
endwhile; 
while($poradi != 4) { 
      $poradi++; 
      echo "<td width=\"280\">&nbsp;</td>"; 
}
echo "</tr>"; 
echo "</table>";

Částečně to funguje, jak bych si představovala.

Pokud mám počet záznamů, který není dělitelný 4, tak to vypíše OK.


Ale když je počet záznamů dělitelný 4, tak mi tam automaticky naskočí pod tabulku jeden volný řádek.


Snažila jsem se dopátrat na internetu, zda je cyklus napsán správně, ale asi tam bude chyba v html syntaxi použití (nevhodně umístěno)
<tr></tr> ?

Nebo opravdu bude chyba ve špatném vyhodnocování podmínky?

Děkuji za upřesnění.
Alphard
Profil
Kombinace </tr><tr> se vypisuje i za posledním záznamem, což přidává ten řádek. Buď ten kód trochu rozdělit podle např. Nejčastější potíže s PHP (FAQ) » Výpis výsledků z databáze (nebo z jiného zdroje) do tabulky o více sloupcích, nebo v tom vašem kódu kontrolovat, jestli se už nevypisuje poslední záznam.
Lucyk
Profil
Alphard:
Děkuji za objasnění. V případě, že bych ve stávajícím kódu přidala vyhodnocování, zda se vypisuje poslední záznam, tak mě napadá nahrazení části kódu tímto:

if ($poradi == 4) { 
      echo "</tr><tr>"; 
      $poradi = 0; 
}
if (($poradi == 4) && ($poradi != 4)) continue;
endwhile; 

Původně jsem to chtěla zkusit přepsat do řešení, na které jsi dával odkaz, ale zasekla jsem se na tom kdy tam je použit cyklus for, zatímco já začínám while(list($rok, ... .

Ale myslím, tento řádek by nebyl dobře:
for ($i = 0; list($rok,$vyrobce,$sada) = mysql_fetch_assoc($navrat); $i++)
Keeehi
Profil
Lucyk:
Ale myslím, tento řádek by nebyl dobře:
Byl by dobře.
Lucyk
Profil
Keeehi:
Tak to pak netuším, co tam mám špatně, neboť po nahrazení touto částí kódu mi to hlásí:

Undefined variable: sloupce in
Warning: Division by zero in

define ("$sloupce", 4);  // počet sloupců
 
echo "<table>\n";
for ($i = 0; list($rok,$vyrobce,$sada) = mysql_fetch_row($navrat); $i++)
{
  if ($i % $sloupce == 0) echo "<tr>";
  echo "<td width=\"280\"><a href=\"index.php?rok=$rok&vyrobce=$vyrobce&sada=$sada\"></a></td>";     
  if ($i % $sloupce == $sloupce - 1) echo "</tr>\n";
}
if ($i % $sloupce != 0)
{
  while ($i++ % $sloupce != 0)
  {
    echo "<td>&nbsp;</td>";
  }
  echo "</tr>\n";
}
echo "</table>\n";

Pokud vyměním tento řádek:
for ($i = 0; list($rok,$vyrobce,$sada) = mysql_fetch_assoc($navrat); $i++)

Tak to hlásí
Undefined variable: sloupce in
Undefined offset: 2 in
Undefined offset: 1 in
Undefined offset: 0 in

Tento řádek define ("$sloupce", 4); // počet sloupců neplní funkci definice proměnné?



Podařilo se mi upravit svůj stávající kód s while následovně, ale netuším, zda je to tak dobře, neboť u konce si nejsem jistá, zda tam není navíc echo "</tr>";.

echo "<table id='tabulka_vypis'>"; 
echo "<tr>"; 
$poradi = 0;
while (list($rok,$vyrobce,$sada) = mysql_fetch_row($navrat)): 
echo "<td width=\"280\"><a href=\"index.php?rok=$rok&vyrobce=$vyrobce&sada=$sada\"></a></td>"; 
$poradi++;
if($poradi == 4) { 
      echo "</tr><tr>"; 
      $poradi = 0; 
}
endwhile; 
if($poradi == 0) { 
      echo "</tr>";  
      } else {
      while($poradi != 4) { 
            $poradi++; 
            echo "<td width=\"280\">&nbsp;</td>"; 
      }
}
echo "</tr>"; 
echo "</table>";

Sice to už nevypisuje prázdný řádek, ale nezdá se mi tam to, že když bude ($poradi == 0), tak dojde k ukončení </tr> a plus ještě na konci kódu mám znovu ukončení </tr>, tzn. že je tam nyní 2x (přestože jsem nenarazila, že by se to projevilo negativně při výpisu)?
Tomášeek
Profil
Lucyk:
Tento řádek define ("$sloupce", 4); // počet sloupců neplní funkci definice proměnné?
To je konstanta. Přiznávám, že nevím, co to udělá s dolarem na začátku, možná se proměnná nejprve vyhodnotí? Nevím.

Proměnná se deklaruje stejně jako v #5 v posledním kódu na 3. řádu, tedy $sloupce = 4.

neboť u konce si nejsem jistá, zda tam není navíc echo "</tr>";
Ano, je, pokud je poradí rovno nule. Ale ničemu ve výsledku nevadí, ta druhá koncová značka je ignorovaná. Také ničemu nevadí, pokud je neuvedeš, koncová značka </tr>, stejně jako </td> a mnohé jiné jsou nepovinné, ukončí se sami, jakmile bude třeba.

Ta podmínka na řádcích 12-19 pro vypsání prázdných buněk do plného počtu a navíc bez přebytečného konce řádku by mohla být (nevyzkoušeno) if ($poradi > 0 && $poradi < 4).
Kcko
Profil
Lucyk:
Než psát tenhle prasokód, ulož si výsledky cyklu do pole, pole rozděl funkcí php.net/manual/en/function.array-chunk.php a poté už bude velmi snadné provést operaci, kterou potřebuješ.
Keeehi
Profil
Je to naprosto jednoduché. Jen se k tomu musí přistupovat systematicky
echo "<table id='tabulka_vypis'>"; 

$i = 0; 
while (list($rok,$vyrobce,$sada) = mysql_fetch_row($navrat)) {
    if ($i % 4 == 0) {
        echo "<tr>";
    }

    echo "<td width=\"280\"><a href=\"index.php?rok=$rok&vyrobce=$vyrobce&sada=$sada\"></a></td>"; 

    if ($i % 4 == 3) {
        echo "</tr>";
    }
    
    $i++;
}

if ($i % 4 != 0) {
    while($i % 4 != 0) { 
        echo "<td width=\"280\">&nbsp;</td>";
        $i++;
    }
    echo "</tr>";
}

echo "</table>";
Kcko
Profil
Keeehi:
Zas tak jednoduché ne, jak vidíš dle autorky vlákna ;-)

Tohle mi přijde tedy čitelnější (a to je to zbytečně "komplikované" jen kvůli dopočítání prázdných buněk, což v případě tabulky žádný problém neudělá, takže to tam ani být nemusí).

<?php

$data        = range(1, 9);
$divideBy    = 4;
$chunks      = array_chunk($data, $divideBy);
$rowsTotal   = count($chunks);
$cellsToFill = $divideBy - count($chunks[$rowsTotal - 1]);

echo "<table border=1>";
foreach ($chunks as $rowIndex => $cells)
{
    echo "<tr>";
    foreach ($cells as $cell)
    {
        echo "<td>";
        echo $cell;
        echo "</td>";
    }

    if ($rowIndex == $rowsTotal - 1 && $cellsToFill > 0)
    {
       for ($i = 0; $i < $cellsToFill; $i++)
       {
            echo "<td>&nbsp;</td>";
       }
    }
    echo "</tr>";
}
echo "</table>";
Keeehi
Profil
Kcko:
Tak když se to zarovná, tak by to mohlo být ještě jednodušší.
$data               = range(1, 9);
$divideBy           = 4;
$rows               = array_chunk($data, $divideBy);
$rowsTotal          = count($rows);
$rows[$rowsTotal-1] = array_pad($rows[$rowsTotal-1], $divideBy, null);

echo "<table border=1>\n";
foreach ($rows as $row)
{
    echo "<tr>\n";
    foreach ($row as $cell)
    {
        echo "<td>";
        echo $cell ?? '&nbsp;';
        echo "</td>\n";
    }
    echo "</tr>\n";
}
echo "</table>";
Kód využívá null coalescing operator, který je v PHP od verze 7. V nižších verzích ho lze nahradit ternárním operátorem nebo i obyčejnou podmínkou.

Proč ale zbytečně vytvářet pole a výsledky dvakrát procházet, když to stačí jen jednou?
Kcko
Profil
Keeehi:
Proč ale zbytečně vytvářet pole a výsledky dvakrát procházet, když to stačí jen jednou?
Protože zvítězí čitelnost nad nicotnou operací (dvojí průchod) :)

PS. Zbytečné se o tom dál bavit, at si Lucyk vybere sama.
PS2. Řádek 5 je elegantní.
Lucyk
Profil
Keeehi:
Je to naprosto jednoduché. Jen se k tomu musí přistupovat systematicky
Děkuji, tento zápis je pro mě srozumitelnější. Vím, že u mého kódu už nastal ten problém, kdy jsem měla echo "<tr>"; ještě před začátkem samotného cyklu.

Kcko:
Než psát tenhle prasokód, ulož si výsledky cyklu do pole,
Snažím se čerpat inspiraci u internetu, proto vznikl tento paskvil, který jsem upravovala dle svých potřeb. Jelikož vše testuji na stránkách webzdarma, tak už se mi nejednou podařilo si zacyklit výstup a pak je vždy musím žádat o obnovu :/
Na Tvůj návrh řešení se určitě kouknu a třeba najde u mě využití při sestavování dalších cyklů :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: