Diskuze: Pole v parametru funkce

PHP PHP Pole v parametru funkce American English version English version

Avatar
Paranormal
Redaktor
Avatar
Paranormal:

Ahoj, Mám pole v parametru funkce a potřebuji ti potom přeformulovat na textový řetězec kvůli databázi.

function select($where)
{
        ... WHERE name IN (:where) ...
        ... bindParam(':where', $where) ...

}

Kdybych to tu takhle naznačil tak by se pak volala funkce

$result = select( array("param1","param2","param3") );

Jestli to nejde pochopit tak se omlouvám :D

Editováno 26. května 20:44
Odpovědět 26. května 20:44
„Když toho moc neumíme tak jsme na nejlepší pozici se něčemu naučit.“
Avatar
Pavel Junek
Redaktor
Avatar
Odpovídá na Paranormal
Pavel Junek:

Nevím jestli jsem to pochopil správně, ale zkus

implode(" ", $result)

převede pole na String, kde bude mezi slovy mezera (první parametr)

 
Nahoru Odpovědět  +1 26. května 20:50
Avatar
Martin Štěpánek (Enormyk):

Celý kód by tedy měl vypadat takto:

$pole = array("param1", "param2", "param3");
$result = select($pole);

function select($where)
{
$string = implode(" ", $where);
        ... WHERE name IN (:where) ...
        ... bindParam(':where', $where) ...

}
:-)
Nahoru Odpovědět  +1 26. května 21:06
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Paranormal
Jindřich Máca:

Ahoj, já asi chápu, co potřebuješ, přičemž řešení, co navrhuje Pavel Junek je sice správné, ale já si dovolím sem zatáhnout ještě bezpečnost, hlavně co se týče SQL injection - http://www.itnetwork.cz/…on-a-obrana/.

Já bych to viděl asi nějak takhle, s tím, že v $connection budeš mít uložené PDO spojení:

function select($where)
{
        // Vytvoříš SQL statement.
        $statement = $connection->prepare('... WHERE name IN (:where) ...');

        /* Dosadíš parametry s použitím Pavlova řešení, akorát tam patří ',', a zároveň to spustíš.
           Alternativně by jsi mohl použít 'bindParam()' a pak to teprve spustit.
           Tohle řešení by mělo být bezpečné právě vůči SQL injection - viz. odkaz. */
        $statement->execute([':where' => implode(",", $where)]);

        // Pak už jsi můžeš s výsledkem dělat co chceš, např. vrátit všechny výsledky jako pole.
        return $statement->fetchAll();
}

No a na závěr si k tomu dovolím ještě jednu poznámku. Správně by jsi to totiž měl ještě celé obalit do try-catch bloku a očekávat PDOException při chybě nebo alternativně ty funkce vracejí FALSE při neúspěchu. To už ale záleží na tom, jak máš nastavené PHP. :) No a s tímto už Tě jenom odkáži do dokumentace PDO - http://php.net/…book.pdo.php. ;)

 
Nahoru Odpovědět  +2 26. května 21:45
Avatar
Paranormal
Redaktor
Avatar
Paranormal:

Všem děkuji, nevím kde byla chyba. Teď už to snad půjde :)

Nahoru Odpovědět 27. května 8:24
„Když toho moc neumíme tak jsme na nejlepší pozici se něčemu naučit.“
Avatar
Paranormal
Redaktor
Avatar
Odpovídá na Jindřich Máca
Paranormal:

Prostě to nejde, vyzkoušel sem snad všechno. Ale nefachá to :D

$zadani_uzivatele = "item1, item2, item3";

$pole = explode(", ", $zadani_uzivatele);

select($pole);

funkce select

function select($where)
{
        $stmt = $conn->prepare(" .... WHERE item IN (:items) .....");

        $stmt->bindParam(':items', implode(',', $where));
        $stmt->execute();
        return $stmt->fetchAll();
}

Nevím co tam mám špatně. Když si nechám vypsat jenom to pole v tý funkci tak to funguje. Ale dál to nešlape.

Nahoru Odpovědět 29. května 13:54
„Když toho moc neumíme tak jsme na nejlepší pozici se něčemu naučit.“
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Paranormal
Jindřich Máca:

Tak jsem se v tom ještě vrtal a postup je správný, jenomže bindování parametrů zakazuje použití určitý znaků, právě kvůli obraně proti SQL injection. No a jedním z takových znaků je i ","... :D To ve zkratce znamená, že nemůžeš nabindovat do jednoho identifikátoru hodnotu, ve které jsou jednotlivé sub-hodnoty odděleny čárkami. :)

Takže musíš použít takovou menší kličku a pro to bindování si v tom statementu vygenerovat odpovídající počet parametrů už rovnou oddělených čárkami, přičemž pak se to může celé nabindovat přímo jako to pole.

function select(array $where)
{
        $query = implode(',', array_fill(0, count($where), '?'));
        $stmt = $conn->prepare("... WHERE item IN ({$query}) ...");
        $stmt->execute($where);
        return $stmt->fetchAll();
}

Teď už by to opravdu mělo vrátit správný výsledek, mám to i odzkoušené. ;)

 
Nahoru Odpovědět 30. května 3:04
Avatar
Paranormal
Redaktor
Avatar
Odpovídá na Jindřich Máca
Paranormal:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters' in D:\Programy\XAMPP\htdocs\Searching_Test\db.php:50 Stack trace: #0 D:\Programy\XAMPP\htdocs\Searching_Test\db.php(50): PDO->prepare('\r\n ...') #1 D:\Programy\XAMPP\htdocs\Searching_Test\index.php(10): DB::select(Array) #2 {main} thrown in D:\Programy\XAMPP\htdocs\Searching_Test\db.php on line 50

Udělal jsem to podle tvýho návodu, ale někde je tam chyba. :/

Nahoru Odpovědět 30. května 10:38
„Když toho moc neumíme tak jsme na nejlepší pozici se něčemu naučit.“
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Paranormal
Jindřich Máca:

Ach jo... To je tím, že sem prostě neuvádíš celý ten kód. Ty totiž nemůžeš mixovat např. ":item" a pouhý "?" v jednom dotazu. Takže když já používám pro ty položky v poli "?", nemůžeš tam pro další parametry použít nic jiného než "?".

S těmi otazníky je to sice jednoduší, ale pro jistotu sem uvedu i tu druhou variantu:

function select(array $where)
{
        $keys = array_map(function ($value) {
                return ":item{$value}";
        }, range(1, count($where)));
        $query = implode(',', $keys);
        $stmt = $conn->prepare("... WHERE item IN ({$query}) ...");
        $stmt->execute(array_combine($keys, $where));
        return $stmt->fetchAll();
}

A ještě upozorním, že jelikož se ty parametry jmenují ":item1", ":item2" atd., nesmíš tam nikde používat stejný název pro další vlastní parametry. :)

 
Nahoru Odpovědět 30. května 17:15
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 9 zpráv z 9.