[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]
 
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:
  • 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?
 
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.
 
  • 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:
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:
  • 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:
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..
 
  • 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.
 
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.
 
  • 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?
 
[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:
 
  • 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:
Du musst [kw]'db_displays'[/kw] in Anführungszeichen setzen (egal ob ' oder "), damit ein String draus wird.
 
  • 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]
 
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.
 
  • 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.
 
... 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.
 
  • 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:
Öhm ja, aus dem execute muss der Teil mit db_,table raus. Vorher war Zeit für Feierabend und nun bin ich am Handy..
 
Zurück
Oben