PHP Behandlung von double-Wert 0

raffiSSL

Lt. Junior Grade
Registriert
Feb. 2006
Beiträge
289
Hallo,
ich habe da ein für mich nicht nachvollziehbares Problem in einem PHP-Skript. Ganz konkret geht es um die Behandlung der Eingaben 0 | 0,00 | 0.00 über ein Formular.
Ziel soll es sein diese Werte in eine MySQL-Tabelle zu schreiben, die zugehörige Spalte besitzt den Typ decimal (10,2).
Um die Eingabedaten DB-konform zu wandeln und evtl. kleinere Eingabefehler abzufangen arbeite ich mit folgenden Codezeilen:
PHP:
# ersetze alle Kommata durch Punkte 
$personentage = str_replace(",", ".", $personentage);

# lese float Nummer aus und zähle gefundene Werte
# um evtl. Eingabefehler zu erkennen
$count = sscanf($personentage, "%f%s", $personentage, $temp);

Diesen Zeilen funktionieren soweit mir ersichtlich, das kann ich an der Ausgabe mit Hilfe von FirePHP erkennen. Die problematischen Eingaben führen alle zum gleichen Ergebnis:
  • Wert von $personentage = 0
  • Typ von $personentage = double

Das für mich eigentlich sichtliche Problem tritt beim Ausführen eines insert-Statements weiter unten im Code auf. Dort prüfe ich auf
PHP:
$personentage != NULL
. Wenn ja, dann schreibe die Werte in die DB, wenn false, dann lasse die Spalte im Statement weg und schreibe den default-Wert in die Zelle (NULL).
Hier jetzt nochmal das komplette Statement:
PHP:
### CONTENT_TYPE_AUFTRAG ###
$query = "
			insert into 
				content_type_auftrag 
			(
				vid, nid, field_firma_nid, 
				field_startjahr_value, field_pr_number_value, field_pr_anzeigen_value,
				field_zeit_abfragen_value, field_vkz_value,
				field_auftragskategorie_nid, field_auftrag_uekat_nid
		";
if ($personentage != NULL) {
	$query .= "	, field_auftrag_personentage_value";	
}
$query .= "
			) 
			values
			(
				(
					select
						max(nr.vid)
					from
						node_revisions nr
					where
						nr.nid = $n_id
				),
				$n_id,
				(
					select 
						n.nid 
					from
						node n 
					where 
						n.title=\"$SQLpr_company\" 
							and
						n.type='firma'
				),
				$pr_year, $pr_number, $pr_anzeigen, 1, '',
				(
					select 
						n.nid 
					from
						node n
					where
						n.title=\"$SQLkategorie\"
							and 
						n.type='kategorie'
				),
				(
					select
						n.nid
					from
						node n
					where
						n.title=\"$ueid\"
							and 
						n.type='ueberstunden_kategorie'
				)
			";
if ($personentage != NULL) {
	$query .= "	, $personentage";	
}
$query .= ")";
Die oben genannten Eingaben führen immer dazu, dass NULL in die Zelle geschrieben wird. Nur will ich nicht so recht verstehen warum.

Danke und viele Grüße
 
0 ist und wird nie NULL sein. NULL ist ein "Wert" ohne Wert. 0.0 ist ein Wert, also prüf auf != 0, != 0.0, !== 0.0, > 0 oder < 0.
http://php.net/manual/en/language.types.null.php schrieb:
The special NULL value represents a variable with no value. NULL is the only possible value of type NULL.
 
Wie setzt du den die Variable $personentage, wäre vom Vorteil wenn du immer den kompletten dazugehörigen Code postest ;-)

Grüß,

EDIT

@Yuuri

das Problem ist aber dass die Variable immer NULL ist weil er ja in den else-zweig immer reingeht, oder habe ich es komplett falsch verstanden ?
 
Welcher else-Zweig? Wenn der Wert nicht mit in die DB geschrieben wird und kein Default-Wert gesetzt ist, kommt NULL in die DB an dessen Stelle.
 
stimmt gibt keinen, durch den text 8wenn ja wenn nein) dachte ich es gibt ausserhalb des SQL´s noch eine IF Verzweigung.

Sorry,

grüß,
 
Hallo,
sorry, dass ich vergessen habe die Zeile des Setzens von $personentage zu ergänzen. Das Skript hat den folgenden (eingekürzten) Aufbau:
PHP:
function save_project($method, $drupal_db_link) {
	global $kurztext;
	global $pr_year;
	global $pr_company;
	global $pr_number;
	global $pr_anzeigen;
	global $kategorie;
	global $id;
	global $DRUPAL_DB_NAME;
	global $personentage;
	
	$personentage = str_replace(",", ".", $personentage);
	$count = sscanf($personentage, "%f%s", $personentage, $temp);

        # gibt double aus, nur bei keiner Eingabe string
        fb(gettype($personentage), "Typ von personentage"); 
	fb($personentage, "personentage"); 
       .....
        ### CONTENT_TYPE_AUFTRAG ###
		$query = "
					insert into 
						content_type_auftrag 
					(
						vid, nid, field_firma_nid, 
						field_startjahr_value, field_pr_number_value, field_pr_anzeigen_value,
						field_zeit_abfragen_value, field_vkz_value,
						field_auftragskategorie_nid, field_auftrag_uekat_nid
				";
		if ($personentage != NULL) {
			$query .= "	, field_auftrag_personentage_value";	
		}
		$query .= "
					) 
					values
					(
						(
							select
								max(nr.vid)
							from
								node_revisions nr
							where
								nr.nid = $n_id
						),
						$n_id,
						(
							select 
								n.nid 
							from
								node n 
							where 
								n.title=\"$SQLpr_company\" 
									and
								n.type='firma'
						),
						$pr_year, $pr_number, $pr_anzeigen, 1, '',
						(
							select 
								n.nid 
							from
								node n
							where
								n.title=\"$SQLkategorie\"
									and 
								n.type='kategorie'
						),
						(
							select
								n.nid
							from
								node n
							where
								n.title=\"$ueid\"
									and 
								n.type='ueberstunden_kategorie'
						)
					";
			if ($personentage != NULL) {
				$query .= "	, $personentage";	
			}
			$query .= ")";
}

$personentage = $_GET["personentage"];

if ($method == "new" || $method == "edit") {
	print_form($method, $id, $drupal_db_link);
} elseif ($method == "insert" || $method == "change") {
    save_project($method, $drupal_db_link);
}
Am Ende des Skriptes werden also zuerst cie Variablen per $_GET gesetzt, dann die Funktion save_project aufgreufen, in dieser findet die Behandlung von $personentage statt, als auch das insert-Statement.

Viele Grüße
 
Zuletzt bearbeitet:
1. Bitte übergib Parameter im Funktionsaufruf und nicht per global in der Funktion. Besser wäre der Weg über $personentage = $_GET['personentage'] in der Funktion. Der Weg ist aber immer noch schlechter Stil, da er Seiteneffekte mit sich zieht. Funktionen sollten immer gekapselt gebaut werden und unabhängig von der Umgebung immer das gleiche Resultat liefern. Sind bei dir also alle Variablen nicht gesetzt außerhalb der Funktion, kommt Müll raus.
2. Mach mal bitte ein var_dump( $personentage ) in der Funktion, dann solltest du das Problem eigentlich allein identifizieren können.
 
Zuletzt bearbeitet:
Hast du den Vorschlag von Yuuri schon ausprobiert?

Falls es immernoch nicht gehen sollte, kannst du probieren ob es geht wenn du $personentage als Parameter an die Methode save_project übergibst.

Ich hatte in der Vergangenheit eh schlechte Erfahrungen mit global mal hat es funktioniert mal nicht, deshalb tendiere ich zu der Übergabe alle Werte als Parameter.


Des Weiteren würde ich mich an deiner Stelle über SQL-Injections informieren du speicherst die Variable direkt in die DB.


Edit: to slow :(
 
Zuletzt bearbeitet:
Hallo,

ich möchte ja die angesprochenen Eingaben nicht ausschließen, oder verstehe ich den Vorschlag von Yuuri falsch? Nur wenn über das Formular nichts eigegeben wurde für Personentage, soll NULL in die DB geschrieben werden. Daher prüfe ich ja explizit auf != NULL. Vorher hatte ich einfach nur if ($personentage), dort allerdings sind die angesprochenen Eingaben definitiv false. Das ist überhaupt meine Intention.
Zum Thema Umstruktirierung des Skripts:
Es ist ein älteres Skript, welches ich nur für eine andere Datenbank umschreibe. Im Falle eines komplett neuen Skripts hätte ich allerhöchstwahrscheinlich mit der Parameterübergabe gearbeitet. Derzeit muss das Skript aber vorrangig laufen, größere Veränderungen, die mit evtl. nachgelagerten Problemen einhergehen könnten muss ich erstmal außen vor lassen.
Der Wert scheint ja zumindest richtig anzukommen, laut der FirePHP Ausgabe, von daher veränder ich an der Struktur erstmal nichts.

Zwecks den Injections: Ich arbeite zumindest mit mysql_real_escape_string für die Variablen. Des Weiteren wird das Skript nur firmenintern eingesetzt (ca. 30 Personen) und muss damit (vorerst) nicht den nötigen Sicherheitsstandards entsprechen. Aber der Einwand ist trotzdem berechtigt...:)

Viele Grüße
 
Zuletzt bearbeitet:
Asö ok, ging aus dem SQL nicht hervor dass du damit arbeitest :-)

Prüfe die Variable beim setzen des GET´s doch mal so, vllt funktioniert es dann.

PHP:
$personentage = (isset($_GET['personentage']) ?  $_GET['personentage'] : false;

oder noch genauer wäre

$personentage = (isset($_GET['personentage']) && strlen($_GET['personentage'])) ?  $_GET['personentage'] : false;

danach prüfst du immer mit
PHP:
if(!personentage)

Grüß,
 
Zuletzt bearbeitet:
Hallo Dave,

mit dieser zweiten Variante der beiden klappt es jetzt wie gewünscht, super.

Danke nochmals :)
 
raffiSSL schrieb:
Daher prüfe ich ja explizit auf != NULL. Vorher hatte ich einfach nur if ($personentage), dort allerdings sind die angesprochenen Eingaben definitiv false.
Vorsicht vor dem PHP Autocasting!
Beide Abfragen sind identisch und liefern (u.a.) nur dann true, wenn der Wert
  • true,
  • größer oder kleiner 0 (oder 0.0) oder
  • ein String mit mindestens einem Zeichen ist.
 
Mit Tests wie "$var !=NULL" mus man aufpassen:

PHP:
$d = 0.0;
if ($d == null) {
    echo "null";
} else {
    echo "nicht null";
}

Was gibt dieser Code wohl aus? Überraschung: Er gibt "null" aus. Das Gleiche passiert mit (int) 0, (string) "" und (boolean) false.

Wenn du wirklich nur echte NULL-Werte abfragen willst, benutze den Operator "===" oder die Funktion is_null().
 
Zuletzt bearbeitet:
Hallo nochmal,

danke für die letzten Antworten, war mir nicht bewusst das PHP da so kompliziert oder besser eigensinnig agiert, wieder was gelernt.
Ich hab im Nachhinein die Lösung von Dave noch leicht abgeändert, aufgrund der letzten Posts:
PHP:
$personentage = (isset($_GET['personentage']) && strlen($_GET['personentage'])) ?  $_GET['personentage'] : NULL;

Die if-Abfragen sehen nun so aus:
PHP:
if (!($personentage === NULL)) {...

Falls das immernoch nicht wasserdicht sein sollte, obwohl es derzeit tut, könnt ihr gern noch einen weiteren Kommentar da lassen. :)

Danke
 
Zuletzt bearbeitet:
Lass das "!" weg und schreib' dafür "!==". ;)
 
raffiSSL schrieb:
danke für die letzten Antworten, war mir nicht bewusst das PHP da so kompliziert oder besser eigensinnig agiert, wieder was gelernt.
PHP macht eben eine dynamische Typenbindung, was typisch für Skriptsprachen ist. Das ist kein Problem von PHP, sondern der "Einfachheit halber geschuldet" bzw. das typische "Problem" bei Skriptsprachen. Wenn du den Typ der Variablen mit überprüfen willst, gibt es Operatoren wie === und !==, welche Wert und Typ überprüfen (was ich dir empfehlen würde).
 
Zurück
Oben