• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

[PHP] Bitte um hilfe beim erstellen einer Funktion

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
Kann mir bitte jemand erklären, wie ich daraus eine Funktion machen kann und wie ich sie dann aufrufen kann?
[src=php]# Datenfankverbindung herstellen
$db_connect = db_connect();

// Auslesen der Standorte
if(!isset($_GET['locationid'])){
$statement = $db_connect->query("select * from db_locations");
$locations = $statement->fetchALL(PDO::FETCH_ASSOC);
} else {
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $_GET['locationid']]);
$location = $statement->fetch(PDO::FETCH_ASSOC);
}[/src]
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.560
Wie verarbeitest du die Daten? Grundsätzlich als ein Array von Arrays?

Dann vielleicht so:

[src=php]function fetchLocations ($location = NULL) {
# Datenfankverbindung herstellen
$db_connect = db_connect();

// Auslesen der Standorte
if ($location == NULL) {
$statement = $db_connect->query("select * from db_locations");
return $statement->fetchALL(PDO::FETCH_ASSOC);
} else {
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $location]);
return array($statement->fetch(PDO::FETCH_ASSOC));
}
}

var_dump(fetchLocations()); # Should return all locations
var_dump(fetchLocations("LocationId")); # Should return a single location
[/src]

Edit: Warum:
[src=php]array($statement->fetch(PDO::FETCH_ASSOC));[/src]

damit du immer ein Array mit Arrays als Ausgabe bekommst. Damit kannst du die Ergebnisse ohne Umwege gleich behandeln.
 
Zuletzt bearbeitet:

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #3
Danke Split.
Ich könnte das jetzt blind übernehmen, aber ich verstehe leider nicht ganz was da passiert. Das geht schon bei Zeile 1 mit "function fetchLocations ($location = NULL) {" los und geht weiter, weil du die $_GET-Variable komplett ersetzt hast. Kannst du mir das bitte erklären?

Bislang verarbeite ich das Ganze so:
[src=php]
<?php foreach($locations as $l): ?>
<tr>
<td><span><?= htmlspecialchars($l['city']) ?></span></td>
<td><span><?= htmlspecialchars($l['street']) ?></span></td>
<td><span><a href="edit.php?locationid=<?= htmlspecialchars($l['location_id']) ?>">Editieren</a> | <a href="location-delete.php?locationid=<?= htmlspecialchars($l['location_id']) ?>">Löschen</a></span></td>
</tr>
<?php endforeach; ?>
[/src]

Ich denke man kann das schöner lösen, aber ich muss es am Ende ja auch verstehen und ganz daneben ist es ja nicht, was ich da gemacht habe, oder?
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.560
Ich hab das mal für dich etwas kommentiert.
Die $_GET Variable habe ich mal wieder eingebaut.

[src=php]function fetchLocations ($location = NULL) { // Erstellt die Funktion fetchLocations. "location" ist ohne Angabe eines Parameters an die Funktion gleich NULL sonst der Wert der Übergeben wird
if ($location == NULL) { // Wenn kein Parameter übergeben wird, suche alle Locations und gebe diese zurück
$statement = $db_connect->query("select * from db_locations");
// ....
} else {
$statement->execute(['locationid' => $location]); // Wenn ein Parameter übergeben wird suche die Location über die Id
return array($statement->fetch(PDO::FETCH_ASSOC)); // gibt ein Array mit einem Array zurück wie als ob du eine Liste aller Locations zurück bekommst
}
}

var_dump(fetchLocations()); # Should return all locations // Locations ist hier = NULL als Default, weil kein Wert übergeben wird
var_dump(fetchLocations($_GET['locationid'])); // Übergibt die $GET Variable $locationid an die Funktion und ist damit != NULL sondern die $locationid
[/src]

Zugegeben man könnte $location zu => [kw]$locationid[/kw] (in der gesamten Funtion) umbenennen, das wäre einheitlicher.
Das zweite "var_dump" habe ich mit der $GET-Variable für die "$locationid" ersetzt.
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #5
Ich wollte eben die Funktion anders gestalten, aber ich bekomme es leider nicht hin, so dass ich nochmal um Hilfe fragen muss. Folgendes habe ich gemacht:
[src=php]function readLocations(){
$db_connect = db_connect();
$statement = $db_connect->query("select * from db_locations");
$locations = $statement->fetchALL(PDO::FETCH_ASSOC);
return $locations;[/src]

Verarbeiten möchte ich das Ganze dann so:
[src=php]<?php readLocations($locations); foreach($locations as $l): ?>[/src]

Und dann stellt sich gleich die Frage, wie ich das Ganze auszusehen hat, wenn die Funktion so aussehen soll:
[src=php]function readLocation($locationid){ // $_GET['locationid'] scheint nicht erlaubt zu sein.
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $_GET['locationid']]);
$location = $statement->fetch(PDO::FETCH_ASSOC);
}[/src]

Ich habe natürlich rumprobiert, aber kein funktionierendes Ergebnis hinbekommen.
 
Zuletzt bearbeitet:

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.560
Ich wollte eben die Funktion anders gestalten, aber ich bekomme es leider nicht hin, so dass ich nochmal um Hilfe fragen muss. Folgendes habe ich gemacht:
[src=php]function readLocations(){
$db_connect = db_connect();
$statement = $db_connect->query("select * from db_locations");
$locations = $statement->fetchALL(PDO::FETCH_ASSOC);
return $locations;[/src]

Verarbeiten möchte ich das Ganze dann so:
[src=php]<?php readLocations($locations); foreach($locations as $l): ?>[/src]

Richtig wäre es so, das "return" von "readLocations" wird in die Variable "$locations" gespeichert.
Wichtig ist die Rückgabe als Variable zu speichern damit du mit dem "foreach" darauf zugreifen kannst.

[src=php]<?php $locations = readLocations(); foreach($locations as $l): ?>[/src]

Und dann stellt sich gleich die Frage, wie ich das Ganze auszusehen hat, wenn die Funktion so aussehen soll:
[src=php]function readLocation($locationId){
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $locationId]);
$location = $statement->fetch(PDO::FETCH_ASSOC);
}[/src]

So:

[src=php]function readLocation($locationId){
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $locationId]);
$location = $statement->fetch(PDO::FETCH_ASSOC);
return $location; // Return gibt als Rückgabe die $location-Variable zurück
}[/src]

Und um die Funktion zu nutzen:
[src=php]<?php $location = readLocation($_GET['locationid']); echo $location['deinWertHier']: ?>[/src]
 
Zuletzt bearbeitet:

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #7
Danke einmal mehr Split. So sehen die Funktionen jetzt aus:
[src=php]function readLocations(){
$db_connect = db_connect();
$statement = $db_connect->query("select * from db_locations");
return $locations = $statement->fetchALL(PDO::FETCH_ASSOC);
}

function readLocation(){
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from db_locations where location_id = :locationid");
$statement->execute(['locationid' => $_GET['locationid']]); // $statement->execute(['locationid' => $locationId]); gibt nichts zurück
return $location = $statement->fetch(PDO::FETCH_ASSOC);
}
[/src]

Ich habe also das return direkt in das Statement gepackt. Gut so?
 
Zuletzt bearbeitet:

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.560
@Cyperfriend: Nicht ganz, versuchs mal so..

Also du brauchst bei einem "return" keine Variable angeben, du kannst gleich den Rückgabewert von "fetch" zurückgeben lassen.

[src=php]
function readLocation($locationIdVariable){
$statement->execute(['locationid' => $locationIdVariable]); // Hier der gleiche Name wie in "function" angegeben.
return $statement->fetch(PDO::FETCH_ASSOC);
}[/src]

Wenn du jetzt eine Funktion aufrufst, ist der Name der Variable egal. Wichtig wäre nur es so zu machen:
[src=php]$MeineExterneVariable = readLocation($_GET['locationid']);[/src]

Du übergibst damit an die Funktion "readLocation" den Wert in [kw]$_GET['locationid'][/kw]. Damit du nicht innerhalb der Funktion nicht auf das $_GET Zugreifen mußt, was nicht gut wäre..
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #9
Super. Das ist ja toll. Ich denke jetzt habe ichs so langsam. Die nächsten Aufgaben und Funktionen werden es zeigen.
 

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.728
Ort
in der Zukunft
Eventuell hilft es dir eine Funktion wie ein fremdes Programm / Eine fremde Firma vorzustellen (Ab und an hilft ja der Bezug ins reale Leben).

Eine Firma macht für dich Schrauben nach Wunsch.
Dazu benötigt die Firma die Informationen: Länge, Durchmesser, Gewinde und Anzahl (Das sind die Parameter deiner Funktion).
In diesem Beispiel nehmen wir an das alle 4 Informationen eine Ganzzahl sind (Dem Gewindetyp geben wir hier statt M3 etc. einfach eine 3).
Daher kann man für die Information den Datentyp [int] annehmen.
Wenn du, der Kunde nun also einige Schrauben bestellen möchtest, Übergibst du der Firma die 4 Informationen... diese produziert dann die Schrauben für dich. Das ist eventuell ziemlich aufwendig- dir ist das aber egal - du möchtest nur das Resultat zurück haben: Die Schrauben. Und zwar Einzeln verpackt in einer großen Kiste. Daher bekommst du ein Array() Zurück - also eine Liste von einzelnen Werten.

[src=php]function addNumbers(int $laenge, int $durchmesser, int $gewinde, int $anzahl) : array {
$arr = array(
"laenge" => $laenge,
"durchmesser" => $durchmesser,
"gewinde" => $gewinde,
"anzahl" => $anzahl
);
return $arr;
}[/src]

php Kann das ganze auch ohne Typisierung:
[src=php]function addNumbers($laenge, $durchmesser, $gewinde,$anzahl) {
$arr = array(
"laenge" => $laenge,
"durchmesser" => $durchmesser,
"gewinde" => $gewinde,
"anzahl" => $anzahl
);
return $arr;
}[/src]

ich finde nur es ist mit Angabe der jeweiligen Typen verständlicher ;) und allgemein besser zu lesen auch beim Programmieren.
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #11
Ich habe hier eine Funktion, die ich fast identisch immer wieder brauche. Sie sieht wie folgt aus:
[src=php]function readSelectLocation($locationId){
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from db_displays where fk_locations = :locationid");
$statement->execute(['locationid' => $_GET['locationid']]);
return $statement->fetch(PDO::FETCH_ASSOC);
}[/src]

Es ändert sich nur die abzufragende Datenbank, also in dem Fall "db_displays".

Wie kann ich die Funktion so gestelten, dass ich anstatt "db_displays" beispielsweise "db_computer" oder "db_printer" einsetzen kann. Geht das überhaupt oder muss ich für jeden Bereich eine eigene Funktion schreiben? Wäre das ggf. der Übersicht dienlicher und daher sinnvoller?
 

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.728
Ort
in der Zukunft
[src=php]function readSelectLocation(int $LocationId, string $DBTable){
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from :DBTable where fk_locations = :locationid");
$statement->execute(['locationid' => $LocationId,'DBTable' => $DBTable]);
return $statement->fetch(PDO::FETCH_ASSOC);
}[/src]

Du kannst wie oben von mir beschrieben beliebig viele Infos übergeben - alle die die du eben innerhalb der "Fabrik" benötigst.
In deinem Beispiel oben hast du aber $locationId übergeben und dieses innerhalb der Function (Fabrik) gar nicht verwendet?
mit $_GET['locationid'] greifst du ja direkt auf den URL-Parameter zu.

Aber genau dafür sind ja Funktionen da. Dinge die man oft verwendet sollte man nur einmal schreiben.

PS: Ich habe das oben aus dem Kopf geschrieben - hoffe es stimmt trotzdem :uglyngb:
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #13
Ja, ist ein Fehler. Ich probiere grad was. Gibt später noch einen Thread, weil ich an noch was anderem hänge was mit der Funktion zu tun hat.

Habe die Funktion umgeschrieben und rufe sie wie folgt auf
[src=php]<?php readSelectLocation($_GET['locationid'], db_displays); foreach ($displays as $d)[/src]

Habe natürlich rumprobiert und mit der Variante bekomme ich noch die "wenigste" Fehlermeldung.
Fatal error: Uncaught Error: Undefined constant "db_displays" in
Wenn ich ein "const" oder "string" davor setzen wird es auch nicht besser.
 
Zuletzt bearbeitet:

Rakorium-M

NGBler

Registriert
14 Juli 2013
Beiträge
413
Du musst [kw]'db_displays'[/kw] in Anführungszeichen setzen (egal ob ' oder "), damit ein String draus wird.
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #15
Hab ich, aber dann knallts richtig:
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''db_displays' where fk_locations = NULL' at line 1 in[...] Stack trace: #0[...] PDOStatement->execute(Array) #1 [...] readSelectLocation('1', 'db_displays') #2 {main} thrown in

[...] = Serverpfad zur Datei

Der SQL-Teil sieht so aus (Hoffentlich nicht wieder ein übersehener Flüchtigkeitsfehler)
[src=php]function readSelectLocation($locationId, $db_table) {
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from :db_table where fk_locations = :locationid");
$statement->execute(['locationid' => $locationid, 'db_table' => $db_table]);
return $statement->fetch(PDO::FETCH_ASSOC);
}[/src]
 

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.728
Ort
in der Zukunft
das "string" in function readSelectLocation(int $LocationId, string $DBTable)
definiert das die Funktion einen Parameter vom Typ String erwartet.
Wenn du der Funktion nun eine Zahl vom Typ Int übergibst kommt eine Fehlermeldung.

PHP kann den Typ "erraten" ... dann muss man sich darum nicht kümmern - nur dann passiert oft genau das - man weiß eigentlich gar nicht mit was PHP da gerade arbeitet.

PHP weiß das eine Zeichenkette ein String sein soll - wie Rakorium-M schon geschrieben hat, wenn du die Zeichenkette in Anführungszeichen setzt.

Wenn die Funktion einen Wert zurück gibt (hier bei dir steht return... daher gibt sie etwas zurück) muss die Funktion auch mit

$blabla = readSelectLocation($EineZahlVomTypINT, 'einText');

aufgerufen werden.
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #17
Auch mit Deklaration der Variablen gibt es Fehler. Hatte ich probiert, weil du das ja oben schonmal empfohlen hast.
[src=php]<?php readSelectLocation(int $_GET['locationid'], string "db_displays");[/src]
gibt [src=php]Parse error: syntax error, unexpected variable "$_GET", expecting ")" in[/src]
Wenn ich nur db_displays deklariere, also
[src=php]<?php readSelectLocation($_GET['locationid'], string "db_displays");[/src] meckert PHP halt bei db_displays rum
<?php readSelectLocation($_GET['locationid'], string "db_displays");
Und lasse ich die "Anführungszeichen weg gibts
Parse error: syntax error, unexpected identifier "db_displays", expecting ")"
, wobei das ja geklärt wurde. Nur damit ich auch alle Varianten durch habe, die ich probiert habe.
 

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.728
Ort
in der Zukunft
... meine Antwort hatte sich mit deiner überschnitten...
ich / du / wir sind da in eine Falle gerannt. Die Tabelle im SQL-Query kann nicht über Prepered-Statements ersetzt (und gegen sqlinjection geschützt werden.)

Das sollte hoffentlich besser funktionieren:

[src=php]function readSelectLocation($locationId, $db_table) {
$db_connect = db_connect();
$statement = $db_connect->prepare("select * from $db_table where fk_locations = :locationid");
$statement->execute(['locationid' => $locationid, 'db_table' => $db_table]);
return $statement->fetch(PDO::FETCH_ASSOC);
}[/src]


Zur Erklärung:
Wie oben erwähnt wird ein String mit Anführungszeichen (Doppelt oder Einfach) gekennzeichnet.
Bei Doppelten "Hallo $name" wird die Variable $name aber ausgewertet.

[src=php]$name = 'Bob';
echo "Hallo $name!";[/src]

Gibt "Hallo Bob" aus.

[src=php]$name = 'Bob';
echo 'Hallo $name!';[/src]

Gibt "Gallo $name" aus.

--- [2020-10-27 19:10 CET] Automatisch zusammengeführter Beitrag ---

... hier wirds langsam kompliziert ;D

[src=php]<?php readSelectLocation(int $_GET['locationid'], string "db_displays");[/src]

Hier deklarierst du nichts - hier rufst du eine Funktion auf.
Deklarieren / Definieren tust du dort wo der Bauplan steht.

Wie gesagt ich vergleiche so etwas gerne mit dem realen leben :p
Wo legst du fest welche Werte du für deine Produktion benötigst und wie diese aussehen sollen? Im Werk oder macht das der Kunde bei jeder Bestellung selber / wie sollte es sein?

Die Firma / Fabrik sagt dir sie benötigt 4 Informationen, wobei doch bitte bei Gewinde nicht steht "eines mit vielen rillen" Sondern eine Nummer mit der du was anfangen kannst.

Wenn du nun wie du oben beim Bestellen aber rein schreibst ... "Hallo ich definiere aber das Sie keine Nummer haben wollen sondern einen Text" (Ja der Vergleich passt nicht zu deinen Beispiel, da du hier beide male Text stehen hast). ... findest du das dann eher gut oder weniger? ;)

Daher - der der Aufruft muss sich schlicht an das halten was der, der es definiert hat vorgegeben hat:

Definieren tust du dort wo du die Funktion / die "Farbrik" baust und konstruierst.
 

Cyperfriend

Der ohne Avatar

Registriert
14 Juli 2013
Beiträge
1.123
  • Thread Starter Thread Starter
  • #19
Leider wieder kein Erfolg. Wenn ich die Variablen deklariere ist die Fehlermeldung gleich. Nehme ich die Deklaration weg gibt es
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in [...]

Edit: OK, habe ich verstanden. Ich hatte das int und string vorher an der falschen Stelle eingesetzt. Jetzt habe ich das korrigiert. Fehler ist gleich.^^
 
Zuletzt bearbeitet:

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.728
Ort
in der Zukunft
Öhm ja, aus dem execute muss der Teil mit db_,table raus. Vorher war Zeit für Feierabend und nun bin ich am Handy..
 
Oben