array_unshift-Problem?
scorn
- php
0 lulu0 scorn
0 Sönke Tesch0 scorn
Hallo,
ich habe ein Script geschrieben, dass als Shoutbox dienen soll, aber dank meines mangelnden PHP-Könnens funktioniert es nicht richtig:
Der else-Part wird auch ausgeführt, wenn die ersten zwei Bedingungen false sind.
Ich nehme an, dass die ersten zwei Bedingungen quasi unabhängig von der letzten Bedinung un der else-Anweisung sind, aber ich weiß nicht, wie ich das ändern kann.
Und array_unshift() bereitet mir auch Probleme:
$posts = file("shoutbox/posts.txt");
echo $posts . "<br>";
$posts = array_unshift($posts,$newpost);
echo $posts . "<br>";
$posts = implode('',$posts);
Das gibt dann folgendes aus:
Array
1
Warning: implode() [function.implode]: Bad arguments. in /home/www/web22/html/shoutbox2.php on line 44
Was macht array_unshift() mit meinem Array?
So sieht übrigens das Script als ganzes aus:
<?php
if(isset($submit)) {
echo "<span style="color:red">";
if($name=="Name" OR $name=="") { echo "Namen eingeben!<br>"; }
if($message=="Botschaft" OR $message=="") { echo "Botschaft eingeben!<br>"; }
$aip = getenv($REMOTE_ADDR);
$reip = fopen("shoutbox/oip.txt","r");
$oip = fgets($reip,255);
fclose($reip);
$reip = fopen("shoutbox/time.txt","r");
$ozeit = fgets($reip,11);
fclose($reip);
$azeit = time() - 15;
if($ip==$oip AND $ozeit>=$azeit) { echo "Du darfst nicht häufiger als alle 15 Sekunden schreiben.<br>"; }
else {
$name = htmlentities($name,ENT_QUOTES,"UTF-8");
$message = htmlentities($message,ENT_QUOTES,"UTF-8");
$jetzt = date("D, den j.n.Y um g:i:s");
$newpost = "<div class="blue" onMouseOver="red();beschreib(this.title);" onMouseOut="blue();mout();" title="geschrieben am ". $jetzt . "surfing ". $will . ""><b>" . $name . ": </b>" . $message . "<br><img src="res/shoutbox/line.gif" width="99%" height="3"></div>\n";
$posts = file("shoutbox/posts.txt");
$posts = array_unshift($posts,$newpost);
$posts = implode('',$posts);
$write = fopen("shoutbox/posts.txt","w");
fputs($write,$posts);
fclose($write);
$ip = fopen("shoutbox/oip.txt","w");
fputs($ip,getenv($REMOTE_ADDR));
fclose($ip);
$time = fopen("shoutbox/time.txt","w");
fputs($time,time());
fclose($time);
}
echo "</span>";
}
$posts = file("shoutbox/posts.txt");
for ($r=0; $r<6; $r++) {
echo $posts[$r];
}
?>
Online angucken, kann sich das wer will auf [http://sv.stealthlogin.de/shoutbox2.php]
Kann mir jemand helfen, vor allem das mit der else-Anweisung, wo ich ja offenbar prinzipiell was missverstanden hab, ist mir wichtig!
danke,
scorn
Huhu
Was macht array_unshift() mit meinem Array?
das steht hier
http://www.php.net/manual/de/function.array-unshift.php
Kann mir jemand helfen, vor allem das mit der else-Anweisung, wo ich ja offenbar prinzipiell was missverstanden hab, ist mir wichtig!
die else-Anweisung gehört immer nur zu _einem_ "if"-Ausdruck.
Schau es Dir nochmal hier an
http://www.php.net/manual/de/control-structures.php#control-structures.if
Viele Grüße
lulu
Hut sei mit euch!
das steht hier
Ich weiß, daher hab ich es ja, aber wenn ich $posts dann nachher ausgebe, steht da doch nicht Array sondern "1", aber das sollte es doch eigentlich, oder?!
die else-Anweisung gehört immer nur zu _einem_ "if"-Ausdruck.
Ja, das hab ich ja an dem Fehlverhalten meines Scripts gesehen, meine Frage ist aber vielmehr, wie ich das ändern/umgehen kann.
Gruß,
scorn
Und array_unshift() bereitet mir auch Probleme:
$posts = file("shoutbox/posts.txt");
echo $posts . "<br>";
$posts = array_unshift($posts,$newpost);
echo $posts . "<br>";
$posts = implode('',$posts);Das gibt dann folgendes aus:
Array
1Warning: implode() [function.implode]: Bad arguments. in /home/www/web22/html/shoutbox2.php on line 44
Was macht array_unshift() mit meinem Array?
Das, was in der Anleitung steht :) Informiere Dich bitte, bitte, bitte erstmal darüber, was genau die Funktion file() eigentlich zurück gibt, dann erklärt sich bestimmt auch die erste ausgebene Zeile (http://www.php.net/manual/de/function.file.php, beachte bitte die Beispiele!).
Ähnlich sieht es mit array_unshift() aus: Auch hier solltest Du erstmal in die Anleitung schauen und Dich darüber informieren, was die Funktion zurück gibt (http://www.php.net/manual/de/function.array-unshift.php).
Und sage bitte nicht, Du hättest schon reingeschaut und wüsstest es - das ist ganz offensichtlich nicht der Fall.
Was das else angeht: Gib vor den jeweiligen if-Zeilen Deine Bedingungen 1:1 mit var_dump() aus. Auf Variablen, die von außen kommen (wie Dein $submit zum Beispiel), solltest Du _niemals_ direkt zugreifen, sondern immer nur über die dafür vorgesehenen Felder $_GET, $_POST, $_COOKIE, etc (siehe auch php_info()).
Und gewöhne Dir vielleicht einen etwas übersichtlicheren Schreibstil an. Wenn Du alles in der ersten Spalte anfängen lässt, verlierst Du recht schnell den Überblick - und Leute, die Du um Rat fragst, erst recht.
Gruß,
soenk.e
Und sage bitte nicht, Du hättest schon reingeschaut und wüsstest es - das ist ganz offensichtlich nicht der Fall.
Tut mir leid, das muss ich jetzt aber sagen:
die array_unshift-Funktion hab ich mir angesehen, user comments übrigens auch, jetzt sogar zum zweiten Mal. Da habe ich aber nichts besonderes entdeckt.
Die file()-sache hatte ich aus einem Buch, über dessen Unzulänglichkeit ich mich aber inzwischen schon mehrfach gewundert hab.
Ich habs mir jetzt aber auch nochmal angesehen, habe dass mit den Zeilenendzeichen und Macintosh gelesen (ich benutze Mac), aber das Problem habe ich (glaube ich?) nicht.
Andererseits ist vieles dort für mich auch kryptisch:
Optional kann der Parameter use_include_path benutzt und auf '1' gesetzt werden, wenn in dem include_path ebenfalls nach der Datei gesucht werden soll.
Aber ich denke mal, sowas brauche ich auch nicht?
Btw. was heißt Binary_safe?
Und nochwas:
Anmerkung: Jede Zeile in dem resultierenden Array enthält das Zeilenende ('\0'), weshalb Sie trim() verwenden müssen, falls Sie dieses Zeichen nicht vorhanden sein soll.
Was heißt dieses \0? Das ist in meinem (hab ich das schonmal gesagt?) unzulänglichem Buch nämlich nicht zu finden.
implode() hab ich mir auch durchgelesen und sogar (!) verstanden.
Was das else angeht: Gib vor den jeweiligen if-Zeilen Deine Bedingungen 1:1 mit var_dump() aus.
Damit werd ich mich nu beschäftigen, aber auf Anhieb verstehen muss ich es nicht, oder?
Auf Variablen, die von außen kommen (wie Dein $submit zum Beispiel), solltest Du _niemals_ direkt zugreifen, sondern immer nur über die dafür vorgesehenen Felder $_GET, $_POST, $_COOKIE, etc (siehe auch php_info()).
Wieso? register_globals ist an und bei so nem simplen Script spricht doch nix dagegen? Ok, sicherlich die Lehre vom reinen PHP oder so, aber das krieg ich ja doch nicht hin.
Und gewöhne Dir vielleicht einen etwas übersichtlicheren Schreibstil an. Wenn Du alles in der ersten Spalte anfängen lässt, verlierst Du recht schnell den Überblick - und Leute, die Du um Rat fragst, erst recht.
Überblick hatte ich tatsächlich nicht, als ich das Ding geschrieben hab, aber du hast wahrscheinlich recht..
die array_unshift-Funktion hab ich mir angesehen, user comments übrigens auch, jetzt sogar zum zweiten Mal. Da habe ich aber nichts besonderes entdeckt.
Auf http://www.php.net/manual/de/function.array-unshift.php steht als Syntax:
int array_unshift ( array array, mixed var [, mixed ...])
Das "int" am Anfang mag etwas unscheinbar sein, deutlicher wird's in der Beschreibung:
Diese Funktion gibt die neue Anzahl der in array enthaltenen
Elemente zurück.
Vergleiche das mit der Ausgabe Deines echo-Befehls. Er sagt "1" - und genau das ist passiert, array_unshift() hat "1" Element Deinem Feld hinzugefügt. Diesen Rückgabewert "1" hast Du der Variable zugewiesen, in der eigentlich Dein Feld steht - etwas ungeschickt, wenn man das Feld respektive die Variable noch benötigt :)
Die Warnung von implode() hat hier ihre Ursache. implode() möchte ein Feld als Parameter, Du gibst ihm eine Zahl.
Die file()-sache hatte ich aus einem Buch, über dessen Unzulänglichkeit ich mich aber inzwischen schon mehrfach gewundert hab.
Nun, auf http://www.php.net/manual/de/function.file.php steht
file -- Liest eine Datei komplett in ein Array
Vergleiche auch das mit der Ausgabe Deines echo-Befehls. echo kann mit Feldern ("Arrays") nichts anfangen, deshalb gibt er nur den hilflosen Text "Array" aus.
Wie man Felder zeilenweise ausgibt, findest Du als erstes Beispiel auf obiger Anleitungsseite (ich vermute mal, Du hast einfach die implode()-Zeile falsch positioniert).
Tipp am Rande: Felder lassen sich mit print_r() oder var_dump() zwecks Untersuchung ausgeben (eventuell in einen <pre>-Block einhüllen).
Optional kann der Parameter use_include_path benutzt und auf '1' gesetzt werden, wenn in dem include_path ebenfalls nach der Datei gesucht werden soll.
Aber ich denke mal, sowas brauche ich auch nicht?
Nein, wenn Deine Datei nicht in diesem zusätzlichen Pfad gesucht werden soll, brauchst Du das nicht.
Btw. was heißt Binary_safe?
In Bezug auf file() bedeutet das aller Wahrscheinlichkeit nach, daß die Funktion nicht über einige besondere Werte in Dateien stolpert. Ein Zeichensatz besteht nicht nur aus darstellbaren Buchstaben und Ziffern, sondern auch aus Steuerzeichen. Einige Bytewerte bedeuten beispielsweise "Gib ein A aus" oder "Gib die Ziffer 1 aus", andere "Beginne eine neue Zeile". file() benutzt letztere um die Zeilenenden zu erkennen, es gibt derer aber noch eine ganze Reihe mehr (siehe auch nächster Absatz).
Anmerkung: Jede Zeile in dem resultierenden Array enthält das Zeilenende ('\0'), weshalb Sie trim() verwenden müssen, falls Sie dieses Zeichen nicht vorhanden sein soll.
Jedes Zeichen hat, wie Du sicher weißt, einen numerischen Wert, in der Regel im Bereich von 0 bis 255. Mit dem Rückstrich kannst Du diesen Wert unter anderem direkt angeben; bei "\0" würde also ein einzelnes Byte mit dem Wert Null herauskommen, ein Zeichen, für das es nirgends eine Taste gibt und die Rückstrichgeschichte also unerlässlich ist.
Nullbytes stellen nebenbei bemerkt häufig das Ende einer Zeichenkette im Speicher dar. PHP benutzt AFAIK die andere Möglichkeit, es merkt sich einfach die Länge (weshalb file() sich an Nullbytes auch nicht stören sollte).
Zum Thema Rückstrich siehe auch http://www.php.net/manual/de/language.types.string.php.
Was das else angeht: Gib vor den jeweiligen if-Zeilen Deine Bedingungen 1:1 mit var_dump() aus.
Damit werd ich mich nu beschäftigen, aber auf Anhieb verstehen muss ich es nicht, oder?
Doch, deshalb solltest Du es ja machen :) Es ging mir lediglich darum, daß Du bei der Konstruktion
if (a==1)
blabla();
nicht einfach sagst "Ich habe 20 Zeilen höher a auf 1 gesetzt, also muß diese if-Bedingung funktionieren und blabla() ausführen.". Sowas nennt man trügersiche Sicherheit, und die hat schon so manchen zur Verzweiflung gebracht (bzw. die übersehene Anweisung "a++;" drei Zeilen über dem if).
Deshalb sollte man bei unerklärlichem Programmverlauf besser direkt über den fraglichen Verzweigungen die Bedingung nochmal prüfen, zum Beispiel so:
var_dump(a);
if (a==1)
blabla();
Ich hatte Dich darauf hingewiesen, weil ich in Deinem Code nichts entdecken konnte.
Auf Variablen, die von außen kommen (wie Dein $submit zum Beispiel), solltest Du _niemals_ direkt zugreifen, sondern immer nur über die dafür vorgesehenen Felder $_GET, $_POST, $_COOKIE, etc (siehe auch php_info()).
Wieso? register_globals ist an
register_globals ist seit PHP 4.1 standardmäßig aus. Gut, bei Dir ist es eingeschaltet, entweder weil Du selbst Hand angelegt hast oder eine uralte PHP-Version benutzt (aktuell ist 4.3). Nichtsdestotrotz werden Basiseinstellungen eines Systems (wie register_globals) nicht ohne wichtigen Grund geändert, erst recht nicht, wenn Tausende von Programmen nach dieser Umstellung nicht mehr funktionieren und mühselig umgeschrieben werden müssen - ein Hinweis darauf, daß man auch selbst besser die Finger davon lassen sollte.
Kann natürlich sein, daß Du diesen Sachverhalt nicht kennst.
und bei so nem simplen Script spricht doch nix dagegen? Ok, sicherlich die Lehre vom reinen PHP oder so, aber das krieg ich ja doch nicht hin.
Das hat nichts mit irgendwelchen Ideologien zu tun. Der Grund ist zum ersten, daß man bei dieser Form des "Datenimports" nicht feststellen kann, woher die Daten kommen (URL, Formular, Cookie,..). Schlimmer noch, man kann nicht verhindern, daß jemand von außen über die URL in Skriptinterna eingreift. Konkrekt:
if (($nutzer=="willi") && ($passwort="wutz"))
$loginok=true;
[..]
if ($loginok)
sensible_daten_ausgeben($nutzer);
Diese Passwortprüfung ist nichts wert, weil man sie einfach umgehen kann, indem man das Skript mittels
http://example.com/login?loginok=true
aufruft. Ein zweites Beispiel wäre, daß zwar $loginok oben explizit auf false gesetzt wird, aber man kann immernoch fröhlich fremde Identitäten annehmen, indem statt "?loginok=true" "?nutzer=onkelhotte" an die Adresse gehängt wird. Man muß dazu lediglich eingeloggt sein, was nicht selten lediglich eine simple, ungeprüfte Registrierung erfordert.
Die Beispiele mögen simpel sein, aber das Spielchen lässt sich unendlich fortsetzen. Von daher ist es besser, register_globals nicht zu nutzen bzw. auszuschalten und sich gleich an die Nutzung der entsprechenden Felder zu gewöhnen.
Gruß,
soenk.e