Black Friday Black Friday
Black Friday výprodej! Až 80 % extra bodů zdarma! Více informací zde

Diskuze: Uložení hodnoty do databáze

PHP PHP Uložení hodnoty do databáze American English version English version

Aktivity (1)
Avatar
michal Čepelák:18. května 23:03

Zdravím,
potřeboval bych poradit mám tento kód

Db::connect();
if (isset($_POST['CardId'])){
    $CardId = htmlspecialchars($_POST['CardId'],ENT_QUOTES);
    $user = Db::queryAll('SELECT id,CardId FROM uzivatele WHERE CardId=?', $CardId);
    foreach ($user as $zobuser){
        $zobuser['id'];
    }
    $existuje = Db::querySingle('SELECT COUNT(*) FROM uzivatele WHERE CardId=?', $CardId);
    if ($existuje){
    $vlozit = Db::query('INSERT INTO dochazka (date,id_user,CardId) VALUES (NOW(),?,?)',$zobuser, $CardId   );
 //   Header("Location:dochazka.php");
 //   die;
    if ($vlozit){
        Db::connect();
        $sql = Db::queryAll('SELECT * FROM uzivatele WHERE CardId=?  ', $CardId);
        foreach ($sql as $card){
    echo 'Účast hasiče  '.$card['jmeno'].' '.$card['prijmeni'].'  bylo uloženo';
        }
    }
}else{
    echo 'K tomuto číslu karty není přiřazen žádný uživatel, zaregistrujte kartu';
}
}

na hoře jak je proměná $user bych potřeboval z databáze vytáhnout podle $CardId id uživatele, kterému patří karta ale když dám uložit číslo karty tak se mi id uživatele neuloží a napíšemi hlášku Notice: Array to string conversion in /var/www/html­/sdh/Db.php on line 63
použivám místní wraper PDO pro databazi, nevím jestli tam něco musím upravit nebo to mám špatně napsaný ten kód. Jsem začátečník.
Děkuji moc za rady

 
Odpovědět 18. května 23:03
Avatar
Odpovídá na michal Čepelák
Martin Konečný (pavelco1998):18. května 23:09

Ahoj, předáváš tam $zobuser, což je pole, proto ti to píše hlášku "array to string conversion". Jak máš proměnnou $vlozit, tak do toho dotazu předávej $zobuser["id"].
Je tam víc podivných věcí, ale zatím se budu držet otázky.

Nahoru Odpovědět 18. května 23:09
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na michal Čepelák
Matěj Strnad:19. května 6:42

Proč je u toho prvního dotazu do DB "=?" ? :)

Nahoru Odpovědět  -1 19. května 6:42
Ty vaše internety!
Avatar
Vít Kološ
Člen
Avatar
Nahoru Odpovědět  +1 19. května 7:14
Neopravuj, co není rozbité.
Avatar
Odpovídá na Martin Konečný (pavelco1998)
michal Čepelák:19. května 11:14

Děkuji za radu už to funguje. A jaké jsou tam podivné věci ? vím že tam nějaké jsou ale nevím kde přesně. Rád se nechám poučit.
Děkuji

 
Nahoru Odpovědět 19. května 11:14
Avatar
Odpovídá na michal Čepelák
Martin Konečný (pavelco1998):19. května 13:25

Například první dotaz vůbec nemusí být fetchAll(), jelikož hledáš jenom jednoho uživatele podle $cardId. Tedy ten cyklus je tam zbytečně. Nevím, jak přesně vypadá ta knihovna Db, ale stačilo by něco jako

$query = Db::query('SELECT id,CardId FROM uzivatele WHERE CardId=?', $CardId);
$user = $query->fetch();

Další věc je, proč si prvně žádáš data o uživateli podle $cardId (navíc CardId nepotřebuješ vyhledávat, když to už znáš) a teprve potom zjišťuješ dalším dotazem, zda vůbec nějaký takový záznam existuje? Ten dotaz s proměnnou $existuje je zbytečný, protože pokud v prvním dotazu nic nenajdeš, tak v $user bude FALSE nebo něco takového.

Funkce htmlSpecialChars() se používá na výstupu, ne na vstupu. Proti SQL injection se používají jiné funkce, ale hlavně jelikož používáš parametrizované dotazy, tak si ta knihovna tu proměnnou ošetří sama. Tedy tam vůbec být nemusí a správně by ani neměla.

V podmínce if ($vlozit) se znovu připojuješ k databázi, proč?
Dotaz pod tím je stejný případ jako na začátku - hledáš jednoho uživatele, nepotřebuješ tam nějaký cyklus. Navíc ta data o uživateli si můžeš získat už v tom prvním dotazu, nepotřebuješ další :)

Takovéhle řešení by bylo v pohodě (píšu z hlavy, nemusí být 100% funkční):

Db::connect();

if (isset($_POST["CardId"])) {
        $cardId = $_POST["CardId"];

        $query = Db::query("SELECT * FROM uzivatele WHERE CardId = ?", $cardId);
        $user = $query->fetch(PDO::FETCH_ASSOC);

        if ($user !== FALSE) {
                Db::query("INSERT INTO dochazka (date,id_user,CardId) VALUES (NOW(),?,?)", $user["id"], $cardId);

                echo "Účast hasiče  " . $user['jmeno'] . " " . $user['prijmeni'] . "  bylo uloženo";
        } else {
                echo "K tomuto číslu karty není přiřazen žádný uživatel, zaregistrujte kartu";
        }
}
Editováno 19. května 13:27
Nahoru Odpovědět  +1 19. května 13:25
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
michal Čepelák:20. května 11:23

použivám místní wrapper PDO vic příloha
tento kód

$user = Db::queryAll('SELECT id,CardId FROM uzivatele WHERE CardId=?', $CardId);
    foreach ($user as $zobuser){
        $zobuser['id'];
    }

tam mám protože potřebuji získat z tabulky uzivatele, id uživatele ke kterému je přidělena karta, abych pak mohl uživatele zobrazit pod jménem, nevím jestli to jde udělat i jiným způsobem (bohužel jsem začátečník a účím se to).
V kódu co jsi napsal ty tak máš pouze ověření jestli existuje v tabulce uzivatele dané číslo karty(možná se pletu a špatně jsem si to vyložil)

pokud použiju tvůj kód tak mi to napíše
Fatal error: Call to a member function fetch() on integer in /var/www/html­/sdh/dochazka­.php on line 33
ale to je podlě mě skrz ten wrapper PDO co použivám

u podmínky vlozit znovu připojení : to bohužem mi kdysi řekl jeden kolega co použiva mysql ovladač a on u každého příkazu kde bylo připojení do databze znovu připojoval, počitám stím teda že mi stačí dát příkaz pro připojení nahoře na stránce a to bude fungovat pro všechny příkazy připojení.

Doufám že jsem to dobře vysvětlit
Děkuji za rady

 
Nahoru Odpovědět 20. května 11:23
Avatar
michal Čepelák:20. května 11:32

PDO wrapper z místního fora nejde odeslat v příloze tak ho přikládám zde

<?php

/**
 *             __          __                __
 *        ____/ /__ _   __/ /_  ____  ____  / /__ _________
 *       / __  / _ \ | / / __ \/ __ \/ __ \/ //_// ___/_  /
 *      / /_/ /  __/ |/ / /_/ / /_/ / /_/ / ,< _/ /__  / /_
 *      \__,_/\___/|___/_.___/\____/\____/_/|_(_)___/ /___/
 *
 *
 *      TUTORIÁLY  <>  DISKUZE  <>  KOMUNITA  <>  SOFTWARE
 *
 *      Tento zdrojový kód je součástí tutoriálů na programátorské
 *      sociální síti WWW.DEVBOOK.CZ
 *
 *      Kód můžete upravovat jak chcete, jen zmiňte odkaz
 *      na www.devbook.cz :-)
 *
 *  Jednoduchý databázový wrapper nad PDO
 */
class Db
{
        /**
         * @var PDO Databázové spojení
         */
        private static $connection;

        /**
         * @var array Výchozí nastavení ovladače
         */
        private static $options = array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
                PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
                PDO::ATTR_EMULATE_PREPARES => false,
        );

        /**
         * Připojí se k databázi pomocí daných údajů
         * @param string $host Název hostitele
         * @param string $database Název databáze
         * @param string $user Uživatelské jméno
         * @param string $password Heslo
         */
        public static function connect($host="localhost", $database="sdh", $user="root", $password="")
//      public static function connect($host="localhost", $database="sdh", $user="sdh", $password="")
//      public static function connect($host, $database, $user, $password)
                {
                if (!isset(self::$connection)) {
                        $dsn = "mysql:host=$host;dbname=$database";
                        self::$connection = new PDO($dsn, $user, $password, self::$options);
                }
        }

        /**
         * Spustí dotaz a vrátí PDO statement
         * @param array $params Pole, kde je prvním prvkem dotaz a dalšími jsou parametry
         * @return \PDOStatement PDO statement
         */
        private static function executeStatement($params)
        {
                $query = array_shift($params);
                $statement = self::$connection->prepare($query);
                $statement->execute($params);
                return $statement;
        }

        /**
         * Spustí dotaz a vrátí počet ovlivněných řádků. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return int Počet ovlivněných řádků
         */
        public static function query($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->rowCount();
        }

        /**
         * Spustí dotaz a vrátí z něj první sloupec prvního řádku. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Hodnota prvního sloupce z prvního řádku
         */
        public static function querySingle($query) {
                $statement = self::executeStatement(func_get_args());
                $data = $statement->fetch();
                return $data[0];
        }

        /**
         * Spustí dotaz a vrátí z něj první řádek. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Pole výsledků nebo false při neúspěchu
         */
        public static function queryOne($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->fetch(PDO::FETCH_ASSOC);
        }

        /**
         * Spustí dotaz a vrátí všechny jeho řádky jako pole asociativních polí. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Pole řádků enbo false při neúspěchu
         */
        public static function queryAll($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->fetchAll(PDO::FETCH_ASSOC);
        }

        /**
         * Umožňuje snadné vložení záznamu do databáze pomocí asociativního pole
         * @param string $table Název tabulky
         * @param array $data Asociativní pole, kde jsou klíče sloupce a hodnoty hodnoty
         * @return int Počet ovlivněných řádků
         */
        public static function insert($table, $data) {
                $keys = array_keys($data);
                self::checkIdentifiers(array($table) + $keys);
                $query = "
                        INSERT INTO `$table` (`" . implode('`, `', $keys) . "`)
                        VALUES (" . str_repeat('?,', count($data) - 1) . "?)
                ";
                $params = array_merge(array($query), array_values($data));
                $statement = self::executeStatement($params);
                return $statement->rowCount();
        }

        /**
         * Umožňuje snadnou modifikaci záznamu v databázi pomocí asociativního pole
         * @param string $table Název tabulky
         * @param array $data Asociativní pole, kde jsou klíče sloupce a hodnoty hodnoty
         * @param string $condition Řetězec s SQL podmínkou (WHERE)
         * @return mixed
         */
        public static function update($table, $data, $condition) {
                $keys = array_keys($data);
                self::checkIdentifiers(array($table) + $keys);
                $query = "
                        UPDATE `$table` SET `".
                        implode('` = ?, `', array_keys($data)) . "` = ?
                        $condition
                ";
                $params = array_merge(array($query), array_values($data), array_slice(func_get_args(), 3));
                $statement = self::executeStatement($params);
                return $statement->rowCount();
        }

        /**
         * Vrátí poslední ID posledního záznamu vloženého pomocí INSERT
         * @return mixed Id posledního záznamu
         */
        public static function getLastId()
        {
                return self::$connection->lastInsertId();
        }

        /**
         * Ošetří string proti SQL injekci
         * @param string $string Řetězec
         * @return mixed Ošetřený řetězec
         */
        public static function quote($string)
        {
                return self::$connection->quote($string);
        }

        /**
         * Zkontroluje, zda identifikátory odpovídají formátu identifikátorů
         * @param array $identifiers Pole identifikátorů
         * @throws \Exception
         */
        private static function checkIdentifiers($identifiers)
        {
                foreach ($identifiers as $identifier)
                {
                        if (!preg_match('/^[a-zA-Z0-9\_\-]+$/u', $identifier))
                                throw new Exception('Dangerous identifier in SQL query');
                }
        }
}
 
Nahoru Odpovědět 20. května 11:32
Avatar
Odpovídá na michal Čepelák
Martin Konečný (pavelco1998):20. května 13:29

V tom případě místo konstrukce

$query = Db::query("dotaz");
$user = $query->fetch();

napiš

$user = Db::querySingle("dotaz");

Ty tam děláš zbytečně dva dotazy - jeden na kontrolu, zda existuje záznam, a druhý na výběr dat o uživateli. Jenže můžeš v klidu udělat jeden dotaz na data o uživateli a pokud ti nepřijdou data o uživateli (protože se nic nenašlo), tak to znamená, že takový záznam neexistuje :D

Editováno 20. května 13:30
Nahoru Odpovědět 20. května 13:29
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Martin Konečný (pavelco1998)
michal Čepelák:20. května 13:58

Ale jak zobrazím dole v echo účast hasiče ... tak je tam jméno a příjmení a to vytahuji z tabulky uzivatele, kterou použivám i pro user.
tak nahoře ten foreach musí zůstat nebo se pletu?
úprava kódu

if (isset($_POST['CardId'])){
    $CardId = htmlspecialchars($_POST['CardId'],ENT_QUOTES);
    $user = Db::querySingle('SELECT * FROM uzivatele WHERE CardId=?', $CardId);
   foreach ($user as $zobuser){
        $zobuser['id'];
    }
    $existuje = Db::querySingle('SELECT COUNT(*) FROM uzivatele WHERE CardId=?', $CardId);
    if ($existuje){
    $vlozit = Db::query('INSERT INTO dochazka (date,id_user,CardId) VALUES (NOW(),?,?)',$zobuser["id"], $CardId   );

    if ($vlozit){


    echo 'Účast hasiče  '.$zobuser['jmeno'].' '.$zobuser['prijmeni'].'  bylo uloženo';

    }
}else{
    echo 'Chyba komunikace s databazí, kontaktujte administrátora';
}
}

takle to funguje jak má
vic foto v příloze

 
Nahoru Odpovědět 20. května 13:58
Avatar
michal Čepelák:20. května 13:59

když se na to te´dka dívasm tak je tam zybtečný ta proměná existuje

 
Nahoru Odpovědět 20. května 13:59
Avatar
michal Čepelák:20. května 14:07

když jsem to te´dka zkoušel tak bez této kontroli mi to nevypíše chybu K tomuto číslu karty není přiřazen žádný uživatel, zaregistrujte kartu

 
Nahoru Odpovědět 20. května 14:07
Avatar
Odpovídá na michal Čepelák
Martin Konečný (pavelco1998):20. května 15:49

Tady to vypadá na nepochopení toho, jak ta data získáš z tabulky v databázi.
Máš v podstatě tři možnosti

  1. vybírat více řádků naráz - k tomu slouží metoda queryAll(). Výsledkem je pole záznamů, kdy jeden záznam v poli = 1 řádek tabulky. To používáš v případě, že bys těch uživatelů hledal více naráz, a tedy potom použiješ cyklus (př. foreach), abys je všechny prošel.
  2. vybírat jeden řádek - k tomu slouží metoda queryOne(). Výsledkem je jedno pole (případně objekt třídy \stdClass), které obsahuje data ve tvaru název sloupce => hodnota sloupce, tedy třeba id => 1, jmeno => "Michal,", prijmeni => "Čepelák". To použiješ ty, protože hledáš jednoho uživatele, ale více informací o něm - ID, jméno, příjmení atp.
  3. vybírat jednu konkrétní hodnotu jednoho sloupce - k tomu slouží metoda querySingle(). Výsledkem je jeden řetězec, kterému odpovídá hodnota konkrétního sloupce. Tedy např.
$jmeno = Db::querySingle("SELECT jmeno FROM uzivatele WHERE id = 1");

v proměnné $jmeno bude hodnota sloupce jmeno uživatele, který má id = 1.

Takže když se podíváš na to, co potřebuješ - potřebuješ získat více informací o jednom uživateli podle ID jeho karty. Tedy z výše uvedených možností zvolíš variantu b), tedy metodu queryOne(). Když se podíváš do dokumentačních komentářů (nebo do manuálu PDO), tak zjistíš, že ta metoda vrací buď pole, pokud se záznam našel, nebo FALSE, pokud se nenašel.
Jinými slovy - pokud ti ta metoda vrátí pole, máš jistotu, že takový uživatel existuje, a tedy můžeš zapsat jeho čas příchodu a vypsat jeho jméno a příjmení (a jakákoliv další data, které si vySELECTuješ).
Pokud ti ta metoda vrátí FALSE, pak víš, že takový uživatel neexistuje, a tedy vypíšeš tu hlášku.

Nepotřebuješ žádný dotaz typu COUNT(*) na zjištění, zda uživatel existuje. Nepotřebuješ žádný foreach, když výsledkem dotazu je jeden jediný záznam.

Editováno 20. května 15:51
Nahoru Odpovědět 20. května 15:49
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na michal Čepelák
Martin Konečný (pavelco1998):20. května 15:56

Jen tak mimochodem - do kódu třetí strany bys neměl sahat, zvlášť, když to vůbec není potřeba. Nastuduj si, co znamenají výchozí hodnoty u parametrů.
Metoda Db::connect() přijímá několik parametrů, které mají nějakou výchozí hodnotu. To znamená, že když ty parametry nenastavíš ručně, budou mít tu výchozí hodnotu. Ty, jelikož máš jiné login údaje k databázi, než jsou ty výchozí, bys měl předat hodnoty ručně, a neměnit kód té knihovny. Tedy

Db::connect("localhost", "sdh", "root", ....);

a ne měnit konstruktor té třídy.

Editováno 20. května 15:57
Nahoru Odpovědět 20. května 15:56
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 15 zpráv z 15.