Autor Zpráva
N1CK
Profil *
Ahoj, dělám vlastní CMS a narazil jsem na problém.. Chtěl bych udělat posouvání panelů nahoru a dolu.. Využívám MySQL... Nevím absolutně jak to udělat.. Prostě například mám na webu 3 panely s textem a chci poslední dostat nad ten druhý takže vlastně druhý bude poslední a poslední bude druhý... Mám tabulku v mysql panely a tam mám pouze nazev a obsah panelu.. Možno pozměnit.. Budu rád za každý příspěvek..
Joker
Profil
N1CK:
MySQL je jen úložiště dat, prezentaci neřeší.

Dál mi není jasné, v čem je problém. Pokud mají texty na stránce být nějak uspořádané, prostě se v PHP v takovém uspořádání vypíší. Nebo je za tím ještě něco dalšího?
N1CK
Profil *
Ano, má to být v administraci a panely musí jít příkazem posouvat nahoru a dolu (všechny jsou pod sebou)...


Vlastně posouvání záznámů mysql nahoru a dolů...
Someone
Profil
N1CK:
Přidej sloupec `poradi` a podle toho to řaď.
N1CK
Profil *
Jistě, řazení podle ID neni problém, ale posouvání jak udělat..
Tori
Profil
N1CK:
Ne podle ID, podle jiného, nového sloupce. Když chcete měnit pořadí, nemůžete přece měnit ID záznamů.
Potřebujete nějak rozlišovat, jestli se záznam posouvá nahoru nebo dolu (např. parametrem v URL). Při zpracování si jedním SQL dotazem vytáhnete aktuální + nejbližší následující (nebo předchozí) záznam. Pokud dotaz vrátí jen jeden záznam, znamená to, že někdo zkouší posunout poslední záznam ještě dál, teda chyba. Druhým dotazem vyměníte pořadí těch dvou záznamů, zhruba něco takového: SET poradi = IF (poradi = $poradiAktualniho, $poradiNasledujiciho, $poradiAktualniho) WHERE id IN ($aktualni, $nasledujici).
N1CK
Profil *
Já vubec nevim jak to udělat :/ můžete mi říci příkaz na výtáhnutí následujícího (nebo předchozího) záznamu?A teda jak to zaměnit přesněji?Jsem amater.. :/
Tori
Profil
N1CK:
Pardon, zapomněla jsem odkaz: Některé časteji řešené dotazy pro MySQL - FAQ » Data pro další a předchozí záznam vůči $id, když jsou položky seřazeny podle jiného sloupečku než id
N1CK
Profil *
Tak z toho jsem bohužel moc nepochopil :D Nechápu... Potřeboval bych to vysvětlit jak to funguje..
Virtus
Profil
V databázi si přídáte k tabulce další sloupeček s pořadím:
příklad staré tabulky:
CREATE TABLE t1(
  `c1` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `c2` VARCHAR(100),
  `c3` TIMESTAMP DEFAULT NOW(),
  PRIMARY KEY (`c1`)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci;
příklad nové tabulky:
CREATE TABLE t1(
  `c1` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `poradi` INT UNSIGNED NOT NULL DEFAULT 0,
  `c2` VARCHAR(100),
  `c3` TIMESTAMP DEFAULT NOW(),
  PRIMARY KEY (`c1`),
  INDEX(`poradi`)
) ENGINE=MyISAM  CHARACTER SET utf8 COLLATE utf8_unicode_ci;
požadovaný sloupeček do tabulky přidáte v ukázkovém příkladu takto:
ALTER TABLE `t1` ADD `poradi` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `c1`,
ADD INDEX poradi(`poradi`);
Dále je zapotřebí sloupeček `poradi` vyplnit základními daty, pro demonstraci použiju číslování od 1 a nejrychlejší způsob, jaký mně napadá, jak to udělat, je pomocí jednorázového PHP scriptu:
<?php
$mysqli = new mysqli('example.com', 'user', 'password', 'database');
$res = $mysqli->query('SELECT `c1` FROM `t1` ORDER BY `c1` ASC');
$mysqli->autocommit(FALSE);
$poradi = 1;
$queryOk = TRUE;
while( $row = $res->fetch_assoc() ){
  $mysqli->query('UPDATE `t1` SET `poradi` =  ' . $poradi . ' WHERE `c1` = ' . $row['c1']) ? NULL : $queryOk = FALSE;
  $poradi++;
  if( !$queryOk ){
    break;
  }
}
if( $queryOk ){
  $mysqli->commit();
} else {
  $mysqli->rollback();
  echo 'Někde se stala chyba, překontrolujte dotazy a zkuste to znovu.';
}
$mysqli->close();
V tomto momentě mám teda připravno vše, pro to abych mohl dané záznamy přehazovat jak se mi zlíbí.
Předpokládejme že v tabulce `t1` jsou nějaká data.
Na webu si je teda necham vypsat:
<?php
//vypis.php
$mysqli = new mysqli('example.com', 'user', 'password', 'database');
$res = $mysqli->query('SELECT `c1`,`poradi`,`c2`,`c3` FROM `t1` ORDER BY `poradi` ASC');
while( $row = $res->fetch_assoc() ){
  echo ' ID: ' . $row['c1'] . ', sloupec c2: ' . $row['c2'] . ' v čase: ' . $row['c3'] . ',
   <a href="http://www.examle.com/posun.php?smer=%2B&id=' . $row['c1'] . '&poradi=' . $row['poradi'] . '">posuň víš</a>
   <a href="http://www.examle.com/posun.php?smer=-&id=' . $row['c1'] . '&poradi=' . $row['poradi'] . '">posuň níž</a>';
}
$res->free();
$mysqli->close();
A tady obsloužím samotnou změnu pořadí, záznam v přadí 1, tj. ve sloupci `poradi` má hodnotu 1, je brán jako nejníž:
<?php
//posun.php
$match = array();
if( ( ( is_numeric( $_GET['id'] ) ) && ( is_numeric($_GET['poradi']) ) ) && ( preg_match( '/^(\-|\%2B)$/', $_GET['smer'], $match ) ) ){
  $smer = urldecode( $match[1] );
  $badParameter = FALSE;
  $mysqli = new mysqli('example.com', 'user', 'password', 'database');
  $actualRecord = $mysqli->query('SELECT `poradi` FROM `t1` WHERE `c1` = ' . ( int ) $_GET['id'] );
  $actaulRow = $actualRecord->fetch_assoc();
  if( $actaulRow['poradi'] == $_GET['poradi'] ){
    echo 'Špatné parametry ke spracování, záznam, který se pokoušíte přesunout, nemá vámy odeslané pořadí';
    $badParameter = TRUE;
  }
  $actaulRow->free();
  if( !$badParameter ){
    if( $smer == '+' ){
      $poradi = ( int ) $_GET['poradi'] + 1;
    } else {
      $poradi = ( int ) $_GET['poradi'] - 1;
    }
    $res = $mysqli->query('SELECT `c1` FROM `t1` WHERE `poradi` = ' . $poradi );
    if( (int) $res->num_rows ){
      $row = $res->fetch_assoc();
      $queryOk = TRUE;
      $mysqli->autocommit(FALSE);
      $mysqli->query('UPDATE `t1` SET `poradi` =  ' . (int) $_GET['poradi'] . ' WHERE `c1` = ' . $row['c1']) ? NULL : $queryOk = FALSE;
      $mysqli->query('UPDATE `t1` SET `poradi` =  ' . $poradi . ' WHERE `c1` = ' . ( int ) $_GET['id'] ) ? NULL : $queryOk = FALSE;
      if( $queryOk ){
        $mysqli->commit();
        $res->free();
        $mysqli->close();
        header('Location: http://www.example.com/vypis.php'); //vše v pořádku, přesměruj mně zpět na výpis
      } else {
        $mysqli->rollback();
        echo 'Někde se stala chyba, překontrolujte dotazy a zkuste to znovu.';
      }
    } else {
      if( $smer == '+' ){
        echo 'Nelze přesunout záznam víš, je totiž jako poslední, tudíž je nejvíš';
      } else {
        echo 'Nelze přesunout záznam níž, je totiž jako první, tudíž je nejníž';
      }
    }
    $res->free();
  }
  $mysqli->close();
} else {
  echo 'Špatné parametry ke spracování';
}
Tohle berte jen jako ukázkové řešení, podle kterého je možné se inspirovat, počítá to s tím, že sloupec `poradi` bude vždy obsahovat hodnoty z množiny přirozených čísel (N) {1,2,3,...,n}, přičemš n je počet řádků v tabulce `t1` (a z toho vyplívá, že v případě smazání jednoho záznamu z tabulky, musím přepočítat celý sloupce `poradi`). Další nedostatek ukázkového řešení je, že umí přesouvat záznamy pouze o jeden záznam daným směrem.

Co se týče funkčnosti, vytvořím si v tabulce další sloupec s pořadím, tento sloupeč naplním čísli od 1 do n, poté data řadím podle tohoto sloupce a nikoliv podle primárního klíče a poté v něm tyto hodnoty upravuji podle toho, kam sem zrovna jaký záznam přesunul (níž/víš).

V praxy bude potřebovat ještě:
1) dotaz, který Vám zjistí největší číslo pořadí - pro vkládání nových dat
2) algoritmus který bude hledat následující/předchozí číslo v pořadí - pro případ, že by z tabulky byly mazány data a nepřepočítával byste při mazání dat celý sloupec pořadí, v tabulce , v ukázce by se vám záznam, kolem kterého by byl jiný záznam smazán, nepodařilo přesunout, v závisloti na směru posunu, a skript by skončil na jednom z řádku 39, 41 v souboru posun.php.
3) v závisloti na frekvenci přesouvání záznamů, nemusí být přesun pomocí odkazu ideální, možná bude lepší využít třeba AJAX, aby uživatel nemusel čekat na znovu načtení stránky
4) v závislosti natom, o kolik položek je třeba záznamy posouvat, by bylo praktické aby script uměl přesun, třeba, o 5, 10, 20 záznamů
5) Určitě by se našly i další funkce.
Závěrem bych chtěl říct, že ukázkové kódy nemusí 100% fungovat, ale doufám, že Vám pomůžou.
ninja
Profil
Virtus: Tedy radit prasárnu s updatem uvnitř while cyklu doufám myslíte jen jako špatný ftip. To jde přece daleko lépe pomocí:
SET @poradi = 0;
UPDATE tabulka SET poradi = (@poradi:= @poradi + 1) WHERE ...
Virtus
Profil
ninja:
Virtus: Tedy radit prasárnu s updatem uvnitř while cyklu doufám myslíte jen jako špatný ftip. To jde přece daleko lépe pomocí:
>
>
SET @poradi = 0;
UPDATE tabulka SET poradi = (@poradi:= @poradi + 1) WHERE ...
Já bych to nazval leností a nejistotou v mysql, ale jinak s Vámi souhlasím, ovšem když už jste si dal takovou práci, to sem napsat, tak jste to mohl dokončit a rovnou říct, že celý ten script pro naplnění dat sloupečku `poradi`, lze nahradit Vašim dotazem, pro příkladovou tabulku by vypadal takto:
SET @poradi = 0;
UPDATE `t1` SET `poradi` = ( @poradi:= @poradi + 1 );
a ani není potřeba WHERE

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:

0