NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Pole v parametru funkce

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Verquido
Tvůrce
Avatar
Verquido:26.5.2016 20:44

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.5.2016 20:44
 
Odpovědět
26.5.2016 20:44
Avatar
Pavel Junek
Tvůrce
Avatar
Odpovídá na Verquido
Pavel Junek:26.5.2016 20:50

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
26.5.2016 20:50
Avatar
Martin Štěpánek :26.5.2016 21:06

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
26.5.2016 21:06
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Verquido
Jindřich Máca:26.5.2016 21:45

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
26.5.2016 21:45
Avatar
Verquido
Tvůrce
Avatar
Verquido:27.5.2016 8:24

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

 
Nahoru Odpovědět
27.5.2016 8:24
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Jindřich Máca
Verquido:29.5.2016 13:54

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.5.2016 13:54
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Verquido
Jindřich Máca:30.5.2016 3:04

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.5.2016 3:04
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Jindřich Máca
Verquido:30.5.2016 10:38
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.5.2016 10:38
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Verquido
Jindřich Máca:30.5.2016 17:15

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.5.2016 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.