mmofacts.com

Tipps um eval zu vermeiden

gepostet vor 15 Jahre, 4 Monate von BlackScorp

Hallo leute,

ich brauche mal wieder eure Hilfe. Es geht um Folgendes. Ich möchte eine SQL Methode erstellen an die ich mein Query mit eventuellen Parametern überge. Die Anzahl der Parameter sollte dabei keine Rolle spielen. Zur Zeit mache ich das Ganze mit eval. Nur wie ihr bestimmt wisst ist eval = evil:D und man sollte es doch vermeiden. Das Ganze sieht zur Zeit so aus:

http://pastebin.com/m4e1fc47f

und die anwendung so:

PHP:

$db = new DataBase();
$query = "SELECT * FROM pages WHERE name = '%s' AND rights = '%s'";
foreach($db->sql($query,$this->scriptName,'0') as $test)
{
echo $test['id'];
}

 das ganze funktioniert wunderbar nur das eval stört mich ganz schön. gibt es eine sicherere alternative? habe es mit call_user_func_array ausprobiert aber es hat leider nicht funktioniert. als meldung stand da dass sprintf zu viele parameter erhält das ganze sah so in etwa aus:

PHP:

$sql = call_user_func_array('sprintf',array($query,$parameterArray));

 es hat nur funktioniert wenn ich es so gemacht habe

PHP:

$sql = call_user_func_array('sprintf',array($query,$parameterArray[0],$parameterArray[1],usw..));

 jedoch ist es nicht das was ich wollte. also über anregungen würde ich mich freuen.

MFG

gepostet vor 15 Jahre, 4 Monate von Redrick

ich persönlich begreife nicht wozu du überhaupt eval anwendest, ist IMHO wieder um hundert ecken overengineered

und bei sowas

foreach($db->sql($query,$this->scriptName,'0') as $test)
{
...
}

würde ich jeden tag  beten, dass php-compiler damit gut umzugehen weiss (PHP-Freaks vortreten bitte)

Generell würde ich mir an deiner Stelle erstmal einige bekannte Implementation der DB-Handler anschauen und erst dann entscheiden, ob eigene Implementierung Sinn macht.

Wenn du schon ne Klasse hast, dann würde man gerade als erstes einen result-member vorsehen und auf diesen mit hasResult/NumRows/fetchXXXX oder was auch immer zugreifen.

gepostet vor 15 Jahre, 4 Monate von BlackScorp

naja mein ziel ist es eine belibiege sql anweisung auszuführen und dabei alles automatisch zu escapen ohne dass ich alles per hand eintippen muss. also anstatt

$sql = sprintf("SELECT * FROM foo WHERE bar = '%s'",mysql_real_escape_string('test'));

schreibe ich nur

$db->sql("SELECT * FROM foo WHERE bar = '%s'",'test');

und als sql anweisung kriege ich dann folgenden string:

"SELECT * FROM foo WHERE bar = \'test\'"

das ist mein ziel

MFG

gepostet vor 15 Jahre, 4 Monate von Redrick

das ist mir schon klar, nur nicht warum sprintf da nicht ohne eval ausreicht

irgendwie vermisse ich da etwas sorgfalt in dne überlegungen, sonst wäre dir der schnitzer mit "conntect()" sicherlich sofort aufgefallen

gepostet vor 15 Jahre, 4 Monate von BlackScorp

Original von Redrick

das ist mir schon klar, nur nicht warum sprintf da nicht ohne eval ausreicht

weil man bei sprintf die anzahl der parameter festlegen muss. ich erhalte aber die anzahl setzte alle arrays zu einem string und verwende die parameter über eval. somit spielt es keine rolle wieviele parameter ich an die methode übergebe

irgendwie vermisse ich da etwas sorgfalt in dne überlegungen, sonst wäre dir der schnitzer mit "conntect()" sicherlich sofort aufgefallen

ach ja sry wollte diese methode komplett weglöschen. ignorier die einfach ok?

wegen Datenbank handler. hätteste ein link für einen DB-Handler? habe bei google nur was von phpclasses.org gefunden sind halt irgendwelche codeshnipsel die beschränkt sind

MFG

gepostet vor 15 Jahre, 4 Monate von BlackScorp

ich habe nun das Problem gelöst. Es ist nun sichererer allerdings weis ich nicht genau ob das Ressourcensparend ist

PHP:

public function sql($args)
{
foreach(func_get_args() as $values)
{
$this->sqlArguments[] = $values;
}
for($i = 1;$isqlArguments);$i++)
{
$newArgs[] = $this->sqlArguments[$i];
}
$this->escapedArrays = $this->escapeArray($newArgs);
array_unshift($this->escapedArrays, $this->sqlArguments[0]);
$sql = call_user_func_array('sprintf',$this->escapedArrays);
$sql = mysql_query($sql);
while($result = mysql_fetch_array($sql))
{
$this->sqlResults[] = $result;
}
return $this->sqlResults;
}

 MFG

gepostet vor 15 Jahre, 4 Monate von BlackScorp

ah ok mit vsprintf wird die seite viel schneller als wenn ich an das anfang des arrays die query dransetze. vielen dank nun funktioniert meine klasse so wie ich es haben will

http://pastebin.com/m20ec7f1d

MFG

gepostet vor 15 Jahre, 4 Monate von knalli

Ähm *nicht-mitgekommen*: Kann mir bitte nochmals jemand erklären, warum sprintf nicht funktioniert? Wo ist denn dort die Länge der Argument festgelegt?

gepostet vor 15 Jahre, 4 Monate von BlackScorp

naja wenn ich in dem geposteten quellcode statt vsprintf ,sprintf verwende kommt da ne meldgun to vew arguments ... mit vsprintf gehts irgendwie

gepostet vor 15 Jahre, 4 Monate von buhrmi
Weil die Argumente als array vorliegen und sprintf keine arrays als Argumente nimmt.
gepostet vor 15 Jahre, 4 Monate von BlackScorp

Original von buhrmi

Weil die Argumente als array vorliegen und sprintf keine arrays als Argumente nimmt.

das ist die antwort knalli:D

gepostet vor 15 Jahre, 4 Monate von knalli

Okay, schon klar: sprintf()+func_get_args() = vsprintf(). Und man sollte letzteres nehmen, ersteres ist umständlicher ;)

Ich verstehe nur das Argument mit "fixer Länger" bei sprintf() nicht. Da ist nichts fix.

Anmerkungen: 

sql() und createSql() -- beachten den Sonderfall sqlArguments==0 nicht.

if($select[0] == StrToUpper('select')){ << Sofern sowas, sollte man vorher ein trim() machen. Oder aber einfach einen nicht case sensitiven regulären Ausdruck.

Warum ist connect() static?

gepostet vor 15 Jahre, 4 Monate von BlackScorp

connect ist static damit ich dann aus faulheitsgründen nur eine zeile zur verbindung habe also nciht

$db = new DataBase();

$db->connect($server,usw..);

sondern

DataBase::connect($server,usw...);

aber ich denke das thema hat sich erledigt ich schätze ich sollte das normale mysql nicht mehr in der form verwenden zu viel hier programmieren und da und im endeffekt kann man mit Datenbank Extensions genau das erreichen.

MFG

PS: man hat das lange gedauert bis ich es eingesehen habe:D

Auf diese Diskussion antworten