20. januar 2013 - 21:37Der er
30 kommentarer og 1 løsning
bind_param problem
Hej
Er ved at prøve at lave en lille funktion, som kan eksekverer select sætninger og returnerer et array, men jeg er stødt ind i et problem:
Understående kode er en del af en funktion, hvor jeg har medsendt nogle parametre som et array. Problemet er at de skal sættes ind i bind_param som variabler.
foreach($params as $p_key -> $p_value) { // output vil være: Key=0, Value=var1 }
Så med andre ord har jeg medsendt de variabler der skal skiftes ud med ? i min query, og de ligger i arrayet parrams De skal så sættes ind i bind_param() TypeDef er "s" for string
Det er måske vigtigt at tilføje at jeg godt kan få det til at virke så længe der kun er en ting i arrayet, men når der kommer 2 eller flere er der problemer.
Ved 1 kan man jo gøre som følger foreach($params as $p_key => $p_value) { $var = $p_value }
$stmt->bind_param("$typeDef", $var);
Men hvis der er 2 ? i queryen, og dermed 2 værdier i mit array, så holder det ikke.
Det kan du ikke. Du skal angive de enkelte variabler - ikke et array. Du kan lave nogle krumspring med referencer og ReflectionClass eller call_user_func_array - men på dette område er PDO faktisk en del lettere at have med at gøre
@Arne: Der var den combo igen (array_map/anonymous function) - og den gør godt nok koden væsentlig mere elegant. Jeg må se at få indarbejdet (huske), at den mulighed nu også eksisterer i PHP =)
Forstod ikke funktionen helt, men har læst og læst, set videoer osv, og har for øvelsens skyld prøvet at lave min egen funktion, som returnerer et array med resultaterne fra en select
Det jeg håber I vil gøre er at komme med kommentarer til min funktion så jeg kan lære af det :)
Så med andre ord komme med kommentarer til: 1: Forbedringer 2: Sikkerhedsproblemer 3: Hastighedsproblemer 4: Fejl/problemer der kan komme som der ikke er taget højde for 5: Ting man bør gøre anderledes
Jeg takker mange mange gange for jeres store hjælp - takket være jer, og jeres eksempler mv. er jeg ved at begynde at forstå PDO lidt :)
// --------------------------------------------- // Kører funktionen som returnerer et array // --------------------------------------------- $sql = "SELECT * FROM slet WHERE navn LIKE :name AND telefon LIKE :phone"; $params = array(':name' => '%is%',':phone' => '%9%'); $resultarray = db_select($db, $sql, $params);
// --------------------------------------------- // Udskriver hvis mange resultater // --------------------------------------------- //foreach ($resultarray as $posts) { // foreach ($posts as $r_key => $r_value) { // echo $r_key."-".$r_value."<br />"; // } // echo "<br />"; //}
// --------------------------------------------- // Udskriver hvis der kun er 1 resultat // --------------------------------------------- //foreach ($posts as $r_key => $r_value) { // echo $r_key."-".$r_value."<br />"; //}
Det er ikke klart for mig hvad du opnaar ved at: - loope over params i.s.f. bare at sende dem til execute - loope over raekker i.s.f. at bruge fetchAll
Further, if you need to iterate over the result set, you will need a looping construct that will further impact performance. For these reasons mysqli_fetch_all() should only be used in those situations where the fetched result set will be sent to another layer for processing.
Måske, det er årsagen(?) Det kommer lidt an på, hvordan koden skal bruges, og til hvad
men som jeg laeser det saa siger det at: - foerste have en loekke inden i fetchAll som henter alle raekker og skovler data over i et array - derefter have en ny loekke som gaar igennem array og dermed alle raekker har noget overhead
og det har det jo ogsaa sammenlignet med: - en loekke som henter alle raekker og processer dem
men det har ikke mere overhead end: - foerste have en loekke i egen PHP kode som henter alle raekker og skovler data over i et array - derefter have en ny loekke som gaar igennem array og dermed alle raekker
Kan godt være jeg får det lavet for tungt på den måde, men i så fald hvad hvordan vil du så ændre den, så man stadig får et array tilbage og dermed ikke er begrænset i brugen på siden, så den både virker hvis der er et eller mange resultater?
Okay, så burde godt kunne bruge min funktion, og den er også beskyttet i henhold til injection min. ligeså godt som med real_escape_string før i tiden ik?
Mange tak for den store hjælp - hvis der ligges et svar så er der selvfølgelig point :)
@Arne: Jeg mener heller ikke, der er noget problem ved alm. forespørgsler (men nok ved meget store result set). Jeg pointerede blot, at det kunne være dét, der var årsagen til fremgangsmåden =)
#12: Ja og Nej. Nu er du beskyttet ... det var du ikke før i tiden med mysql_real_escape_string *o)
Hvis man bruger mysql_real_escape_string og husker: - at bruge det paa alle strenge - at bruge noget andet paa alle tal - at altid sende connection med saa burde det vaere sikkert.
Jeg har ihvertfald aldrig hoert om sikkerheds problemer med det.
Men med konsekvent brug af prepared statement er der ikke saa meget at huske.
Lige et tillægsspørgsmål til det med bind_value og bind_param - stiller det her da vi har snakket om det, men opretter gerne et nyt spørgsmål, så I kan få point for svar
Nu har jeg en sql sætning
$sql = "SELECT * FROM personer ORDER BY :columnorder ASC";
Men $query->bindValue(":columnorder", "navn"); ser kun ud til at virke på værdier og ikke på kollonne navne.
Problemet er at :columnorder hentes gennem en $_GET, så det er vel farligt at sætte den direkte ind. Fandt en der hed bind_Column, men den virker ikke, og ser heller ikke ud til at være til formålet, når jeg læser om den.
Så hvordan får jeg et kollonne navn sikkert ind i SQL sætningen når det kommer fra en $_GET?
- og det er derfor nok ikke hensigtsmæssigt at bruge kolonnenavne fra brugeren. Så vil du være nødt til at strikke SQL sammen af udefrakommende input - og så ryger sikkerheden ved prepared statements
Tak for svarene. Det er fordi man skal kunne trykke på en kollonne overskrift i en tabel, og så sorterer den efter det, og kollonnerne er dynamisk genereret.
Så det bliver lidt svært at at generer en sql pr stk. da der kan være forskelligt antal kollonner mv.
Men det er mysql så det andet kan måske bruges....... Hvordan fungerer ORDER BY IF(?,feltA,feltB) og hvorfor er det sikkert?
For der kan jo være mange der skal hentes via en query, og dermed en stor mængde data.
Så derfor hentes det jo således at man får f.eks. 100 resultater, og så står der side 2, 3, 4 osv nede i bunden. Og skifter man her, så henter den igen, men hvis man vælger at sorterer, så skal den jo vises de første 100 efter alle er sorteret.
Den med feltA, feltB osv bliver også svær så, da det skal genereres dynamisk, og man skal kunne klikke på alle overskrifterne, men det kunne lade sig gøre.
Men det er da egentlig underligt der ikke findes en måde at benytte et felt i en sql sætning, uden at det giver problemer :(
Fandt en på en side der skrev det kunne gøres således:
$orders=array("name","price","qty"); $key=array_search($_GET['sort'],$orders)); $order=$orders[$key]; $query="SELECT * from table WHERE is_live = :is_live ORDER BY $order";
På den måde skal det være en af dem i arrayet, så det burde jo være sikkert. Ikke nemmeste løsning, men enddog nok den eneste lige umiddelbart ik?
Med hensyn til hvorfor det er saadan, saa haenger det sammen med hvad der sker bag scenen.
Det er faktisk prepare som sender SQL saetningen til MySQL og execute kalder den kun med nogle vaerdier.
Saa allerede ved prepare skal MySQL "compile" SQL saetningen.
Det er svaert at compile hvis tabel og felt navne er input.
Det er nemmere at compile hvis det kun er vaerdier som er input.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.