der Henry: PHP dynamische Variablenerzeugung

Hallo,

ich hätte da ein kleines PHP Problem/Frage.

Ich frage meine Datenbank ab und bekomme mehrerer "Zeilen" zurück. Diese möchte ich jeweils in ein Assoziative Arrays schreiben/erzeugen dann alle Assoziative Arrays in ein Array packen und an den Brwoser senden.

Hierzu habe ich gelesen, das man Variablen auch dynamisch erzeugen kann.

Somit habe ich nachfolgendes probiert, was aber einen Fehler beim "echo" bringt ... Variable nicht vorhanden. (... Undefined variable $T1.drehzahl)

echo $row["plcvarname"];  // hier steht T1.drehzahl
$$nameString = [ "actvalue" => $row["actvalue"], "unit" => $row["unit"] ]; 

				echo ${'T1.drehzahl'}->unit;
			
				$array[] = $$nameString;		

Wo liegt mein Denkfehler ??

Vielen Dank !!

  1. Hallo Henry,

    Hierzu habe ich gelesen, das man Variablen auch dynamisch erzeugen kann.

    Aber nicht sollte. Das ist ein Unfall, der darauf wartet, zu passieren. Wenn Du Daten unter einem namentlichen Schlüssel ablegen willst, tu es im sicheren Namespace eines assoziativen Arrays. Die lassen sich beliebig tief schachteln.

    Undefined variable $T1.drehzahl

    Du hast - zumindest in deinem Code - nirgends etwas an ${'T1.drehzahl'} zugewiesen. Sondern an $$nameString. Was da drin steht, verrätst Du nicht. Es muss was drinstehen, sonst hätte PHP gemeckert, dass $nameString undefiniert wäre.

    Zu meiner Überraschung funktioniert dieser Code, in PHP 5.6, 7.4 und 8.3:

    $name = "T1.drehzahl";
    $$name = 17;
    echo ${'T1.drehzahl'};
    

    T1.drehzahl ist kein erlaubter Variablenname, deshalb meine Überraschung.

    Aber auch wenn das geht, tu es nicht. Wieso baust Du überhaupt das Array in einer Temp-Variablen mit dynamischem Namen zusammen? In deiner Logik würdest Du auch den plcvarname zu den Werten verlieren. Ich würde es eher so machen:

    $array[] = $row;
    

    In $array stünde dann, nach 2 Rows:

    [
      [ "plcvarname" => "T1.drehzahl", "unit" => "U/min", "actValue" => 50000 ],
      [ "plcvarname" => "T1.temperatur", "unit" => "°C", "actValue" => 47 ]
    ]
    

    Alternativ kannst Du das Array auch mit dem plcvarname schlüsseln:

    $array[$row['plcvarname']] = $row;
    

    Dann bekämest Du:

    [
      "T1.drehzahl" => [
        "plcvarname" => "T1.drehzahl", "unit" => "U/min", "actValue" => 50000 ],
      "T1.temperatur" => [
        "plcvarname" => "T1.temperatur", "unit" => "°C", "actValue" => 47 ]
    ]
    

    Der Unterschied ist, dass json_encode Dir mit Variante 1 ein JSON-Array baut und mit Variante 2 ein Objekt. Das Objekt macht Dir im JavaScript vielleicht sogar das Leben leichter.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      vielen Dank für die Antwort !! Bei meinem Beispiel hatte ich die 1. Zeile Code vergessen 🤪

      $nameString = $row["plcvarname"];
      echo $row["plcvarname"];  // hier steht T1.drehzahl
      $$nameString = [ "actvalue" => $row["actvalue"], "unit" => $row["unit"] ]; 
      
      				echo ${'T1.drehzahl'}->unit;
      			
      				$array[] = $$nameString;	
      

      Nach deinem Vorschlag würde ich es nun so machen und nur Teile des "$row" herausziehen um trafic zu reduzieren, da ich bei weitem nicht alle Spalten auf der Webseite benötige.

      $valarray[$row['plcvarname']] = ["actvalue" => $row["actvalue"],
      								 "unit" => $row["unit"],
      												]; 
      

      Wenn ich jetzt auf der Webseite die Daten in json empfange, const data = await response.json();zurückwandle, habe ich ein Array mit Objekten.

      Wie mach ich dann am günstigsten weiter ... das Array in einzelne Objekte zerlegen, oder ???

      1. Hallo Henry,

        Wenn ich jetzt auf der Webseite die Daten in json empfange, const data = await response.json();zurückwandle, habe ich ein Array mit Objekten.

        Nein, hast Du nicht. Ein assoziatives Array wird in PHP von json_encopde als Objekt serialisiert, du bekommst in JavaScript also ein Objekt. Die plcvarname-Werte sind die Eigenschaftsnamen, die { unit, actvalue } Objekt die Eigenschaftswerte.

        Wie mach ich dann am günstigsten weiter ... das Array in einzelne Objekte zerlegen, oder ???

        Wie ich schon Felix schrieb: die eine Wahrheit gibt es nicht. Wenn Du in JS ein Array empfangen willst, musst Du in PHP auch ein JSON-Array erzeugen. Wie das geht, habe ich Dir gestern aufgeschrieben.

        Ob ein Array (kann man mit .forEach() oder for...of durchlaufen) oder ein Objekt (kann man zum Beispiel mit for...in durchlaufen, siehe Felix) für dich besser ist, hängt davon ab, was Du alles damit tun willst. Siehe meine Antwort auf Felix. Isoliert betrachtet kann man nicht sagen, was günstiger ist.

        Rolf

        --
        sumpsi - posui - obstruxi
    2. Lieber Rolf,

      [
        "T1.drehzahl" => [
          "plcvarname" => "T1.drehzahl", "unit" => "U/min", "actValue" => 50000 ],
        "T1.temperatur" => [
          "plcvarname" => "T1.temperatur", "unit" => "°C", "actValue" => 47 ]
      ]
      

      hier doppeln sich die Array-Schlüssel mit dem Wert von plcvarname im so indizierten (Sub-)Array. In meinen Projekten ist es mir lieber, dass der Schlüssel alleine als plcvarname verstanden wird und der Name „plcvarname“ überhaupt nicht mehr in den Daten steht. Braucht es auch nicht. Ist ohnehin kein guter Variablen- oder Eigenschaften-Name.

      Wenn die JSON-Daten so aussehen, dann kann man daraus in JavaScript bequem die Objekte auslesen:

      {
        "T1.drehzahl": {
          "unit": "U/min",
          "value": 50000
        },
        "T1.temperatur": {
          "unit": "°C",
          "value": 47
        }
      }
      

      Es gibt in diesem per JSON beschriebenen Objekt (Literal) zwei Eigenschaften, nämlich T1.drehzahl und T1.temperatur. Diese Eigenschaften bilden jeweils ein Objekt ab, welches die Eigenschaften unit und value kennt. Wozu die Eigenschaft actValue nennen, wenn es auch value tut...

      Mit einer for..in-Schleife lassen sich nun die Eigenschaften auswerten:

      const json = await response.json();
      
      for (let name in json) {
        console.log(
          "Eigenschaft",
          name,
          "wurde ausgelesen:",
          json[name].value + json[name].unit
        );
      }
      

      Liebe Grüße

      Felix Riesterer

  2. Lieber Henry,

    Du machst es zu kompliziert. Das führt nur zu neuen Problemen.

    Im Browser willst Du etwas anzeigen. Das besteht im Wesentlichen aus einem Namen (steht bei Dir in plcvarname), einem Wert (actvalue) und einer Einheit (unit). Die Website sollte es nicht kümmern, wie die Daten in der Datenbank abgelegt werden. Sie sollte die Daten bereits so ausgespielt bekommen, dass sie diese ideal anzeigen kann (siehe meine Antwort auf Rolfs Antwort).

    $json_data = [];
    
    foreach ($db_daten as $row) {
    
      $json_data[$row['plcvarname']] = [
        'unit' => $row['unit'],
        'value' => $row['actvalue']
      ];
    }
    
    echo json_encode($json_data);
    

    In der Foreach-Schleife wird das Array $json_data bei jedem Durchlauf mit einem neuen Wert befüllt, der seinerseits ein Array ist. Der Schlüssel, unter dem dieses neue Array in $json_data abgespeichert wird, ist der Wert in der DB-Spalte plcvarname. Jedes dieser neuen Arrays hat nur zwei Werte, die mit den Schlüsseln unit und value hinterlegt werden. Damit erhältst Du ein Array, dessen Werte nicht nach numerischen Schlüsseln abgelegt sind, sondern unter echten Namen. Gleiches gilt für die Arrays in den Werten. Das macht ihre Auswertung mit JavaScript später sehr günstig.

    Liebe Grüße

    Felix Riesterer

    1. Dieser Beitrag wurde gelöscht: Der Beitrag ist ein Duplikat eines anderen Beitrags.
    2. Hallo Felix,

      ich habe eine Weile überlegt, ob plcvarname in den Wert mit hineinsollte oder nicht.

      Warum nicht?

      • Spart Speicher
      • Spart Übertragungsbandbreite
      • Redundanz triggert meinen inneren Monk

      Warum?

      • Man kann einen Propertywert ohne Aufwand durch die Gegend reichen und weiß den Namen noch
      • Die Erstellung des JSON-Objekts ist einfacher und schneller, man muss nichts umkopieren
      • Die ersten beiden "Warum nicht" Gründe waren 1999 relevant. Heute sind sie es nur dann, wenn ich 1000 Propertywerte oder mehr durch die Gegend schiebe.
      • Meine innere Sharona sagt meinem inneren Monk, dass er damit zu meinem inneren Dr. Kroger gehen soll. Hä?

      Die gleichen Überlegungen gelten bei der Frage JSON-Array oder JSON-Objekt. Wenn ich das Array clientseitig nur einmal durchlaufe und die Eigenschaften anhand des plcvarname irgendwohin schreibe, brauche ich kein Objekt. Wenn ich auf die Eigenschaften clientseitig ständig namensgesteuert zugreifen muss, macht ein Objekt die Sache einfacher. Das weiß nur Henry, das muss er abwägen.

      Es gibt nicht die eine, richtige Lösung.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Guten Morgen,

        vielen Dank euch beiden, auch für die Erklärungen warum so oder so, Vorteile und Nachteile, das macht auch das Verständnis einfacher … wieder was gelernt 👍

        Ich mache mir Objekte und mit diesen die ersten Schritte in JS.

        Schau ma mal … 😉

        Nochmals vielen DANK euch beiden.