Kalle_B: Assoziatives Array

Hallöle,

schlage mich in PHP3 mit assoziativen Arrays herum. Benötige sie, um Keys und Werte an eine Unterroutine zu übergeben.

Habe das Konzept nicht verstanden iund suche das AHA- Erlebnis.

Eine Datenbank- Auswertung ist so einfach:
  $row = mysql_fetch_array( $result );
  $nachname = $row['nname'];

$row ist doch ein assoziativen Array, oder?

Jetzt mein selbstgestricktes:

$adressen = array (
  array (
   'nname' => 'Meyer'
  ,'vname' => 'Hans'
  )
 ,array (
   'nname' => 'Lehmann'
  ,'vname' => 'Fritz'
  ,'ort'   => 'Hamburg'
  )
);

echo $adressen[1]['vname']."<br>";

ergibt Fred, soweit okay.

function auswertung( $array ) {
  /*
  hier möchte ich gezielt den Key3 des zweiten Elements abfragen.
  Das Ergebnis muss Hamburg sein.
  Wie geht das?
  */
}
auswertung( $adressen );

Lieben Gruß, Kalle

  1. hi,

    Eine Datenbank- Auswertung ist so einfach:
      $row = mysql_fetch_array( $result );
      $nachname = $row['nname'];

    $row ist doch ein assoziativen Array, oder?

    Hast du es dir mal mit print_r() angeschaut?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. echo $begrüßung;

      Hast du es dir mal mit print_r() angeschaut?

      Kann er nicht. Aber var_dump() gibt es seit 3.0.5.

      echo "$verabschiedung $name";

  2. echo $begrüßung;

    $row = mysql_fetch_array( $result );
    $row ist doch ein assoziativen Array, oder?

    Jein. Es ist ein "gemischtes" Array. mysql_fetch_array() gibt, wie du dir mit var_dump() mal anschauen solltest, ein Array mit doppelten Werten zurück. Die Keys sind dabei einmal numerisch und zum anderen die Spaltennamen.

    Jetzt mein selbstgestricktes:
    hier möchte ich gezielt den Key3 des zweiten Elements abfragen.

    mysql_fetch_array() gibt ein "gemischtes" Array zurück, weil es das halt so macht. Andere Arrays nehmen sich daran aber kein Beispiel. var_dump() (am besten mit <pre> vorher) zeigt dir das.

    echo "$verabschiedung $name";

  3. Hallöle,

    Habe das Konzept nicht verstanden und suche das AHA- Erlebnis.

    Ein AHA- Erlebnis war es nicht gerade, mehr ein hartnäckiges, stundenlanges Ausprobieren in PHP3 **frustablass**.

    Habe akzeptiert, dass man zumindest auf die Keynamen NICHT direkt zugreifen kann und sie IMMER von 0 (Null) durchhecheln muss. Auch die Werte stehen nicht direkt zur Verfügung, wenn man den Keynamen nicht kennt:

    $adressen = array (
      array (
       'nname' => 'Meyer'
      ,'vname' => 'Hans'
      )
     ,array (
       'nname' => 'Lehmann'
      ,'vname' => 'Fritz'
      ,'ort'   => 'Hamburg'
      )
    );

    function KeyName($myArray,$pos,$upos) {
      if ( ($pos < 0) || ( $pos >= count($myArray) ) )
        return "NULL";  // set this any way you like

    reset($myArray);
      for($i = 0;$i < $pos; $i++) next($myArray);
      reset($myArray[$i]);
      for($j = 0;$j < $upos; $j++) next($myArray[$i]);

    return key($myArray[$i]);
    }
    function Wert($myArray,$pos,$upos) {
      if ( ($pos < 0) || ( $pos >= count($myArray) ) )
        return "NULL";  // set this any way you like

    reset($myArray);
      for($i = 0;$i < $pos; $i++) next($myArray);
      reset($myArray[$i]);
      for($j = 0;$j < $upos; $j++) next($myArray[$i]);

    return current($myArray[$i]);
    }

    echo KeyName( $adressen, 1, 2 ); // ergibt ort
    echo Wert( $adressen, 1, 1 );    // ergibt Fritz

    Muss man da wirklich so einen Zirkus betreiben? Habe mir das mal mit var_dump angesehen. Damit kann ich aber wohl nicht ZUGREIFEN ?

    Lieben Gruß, Kalle

    P.S. Vor dem Abschicken dieses Beitrags kam noch:
    Fehler

    Das Format Ihres Postings scheint unsauber zu sein (z. B. keine Zeilenumbrüche, keine Satzzeichen, alles klein geschrieben oder ähnliches). Solche Postings sind ungern gesehen, da sie oft schwer zu lesen sind. Sind Sie sicher, dass Sie so posten möchten?

    Ich habe wohl meine unsauberen Tage **seufz**

    1. echo $begrüßung;

      Muss man da wirklich so einen Zirkus betreiben [wenn man numerisch auf assoziative Keys zugreifen will]?

      Ein assoziatives Array ist nun mal kein numerisches. Sag doch mal, was dein Problem ist, dass du nicht assoziativ zugreifen kannst?
      PHP4 kennt die Funktion array_values(). Die gibt das Array mit numerischen keys zurück, egal was für Keys bisher drin standen, aber das kannst/darfst du ja anscheinend nicht verwenden.

      Habe mir das mal mit var_dump angesehen. Damit kann ich aber wohl nicht ZUGREIFEN ?

      var_dump() ist nur zur Ausgabe von Variableninhalten da und im Allgemeinen nur für das Debuggen sinnvoll verwendbar.

      echo "$verabschiedung $name";

      1. Hallo, dedlfix,

        Sag doch mal, was dein Problem ist, dass du nicht assoziativ zugreifen kannst?

        Ich habe die Bildschirm-Ausgabe komplett ausgelagert.

        Einerseits in eine htm-Datei MIT PLATZHALTERN. Damit kann ich das Layout vorab lokal ohne PHP und ohne Daten betrachten und bearbeiten:

        <style .... /style>
        <!-- [kopf] -->
        <table>
        <tr>
          <th>Name</th>
          <th>Tel</th>
        </tr>
        <!-- [/kopf] -->
        <!-- [position] -->
        <tr>
          <td>[vorname]</td>
          <td>[mobilnr]</td>
        </tr>
        <!-- [/position] -->
        <!-- [fuss] -->
        </table>
        <!-- [/fuss] -->

        Andererseits in ein function, dessen Aufgabe es ist, diese htm-Datei einzulesen, die Platzhalter zu ersetzen und per echo auszugeben. Dieses function ist natürlich für ALLE Programme des Projekts dieselbe, also kennt sie nicht die Namen der Platzhalter.

        Im ersten Anlauf habe ZWEI Arrays übergeben, im ersten die Namen und im zweiten die Werte. Das ist beim Aufbau der beiden Arrays natrlich sehr fehleranfällig, wie leicht kann man da was übersehen.

        $platzhalter = array(
          array( "position","[vorname]","[mobilnr]" )
         ,array( "position","[vorname]","[mobilnr]" )
         ,array( "position","[vorname]","[mobilnr]" )
        );
        $daten = array();
        $zeile = 0;
        while ( $row = ...
          $daten[$zeile][0] = $row['vname'];
          $daten[$zeile][1] = $row['mobil'];
          $zeile++;
        }

        Änderungen/Erweiterungen sind umständlich und fehlergefährdet, weil die Anzahl und Reihenfolge der Elemente in beiden Tabellen genau eingehalten werden muss. Da kam ich auf die Idee mit dem assoziativen Array, das enthält ja die gewünschten Paare:

        $daten = array();
        $zeile = 0;
        while ( $row = ...
          $daten[$zeile] = array(
            'segment' => 'position'
           ,'[vorname]' => $row['vname']
           ,'[mobilnr]' => $row['mobil']
           );
          $zeile++;
        }

        Also muss das function die Keys aus dem Array fischen, weil sie die Platzhalter sind.

        Habe dieses Verfahren der Auslagerung vor ein paar Tagen diskutieren wollen, bekam aber nur eine Antwort. Habe ich jetzt selbst entwickelt, obwohl das doch Thema in fast jedem größeren Projekt sein müsste.

        LG Kalle

        1. echo $begrüßung;

          Sag doch mal, was dein Problem ist, dass du nicht assoziativ zugreifen kannst?

          Ich habe die Bildschirm-Ausgabe komplett ausgelagert. [...]

          Wie deine Template-Geschichte funktioniert, habe ich nicht verstanden. Und grade wollte ich dich auf PEARs Template-Pakete verweisen, als mir wieder einfiel, dass du ja nur mit PHP3 arbeitest. Vielleicht kannst du dir aber dort wenigstens die Arbeitsweise anschauen. HTML_Template_IT ist dabei mein Favorit.

          echo "$verabschiedung $name";

          1. echo $begrüßung;

            ..., als mir wieder einfiel, dass du ja nur mit PHP3 arbeitest. Vielleicht kannst du dir aber dort wenigstens die Arbeitsweise anschauen. HTML_Template_IT ist dabei mein Favorit.

            Habe ich mal reingeschaut. Vorgestern wurde beschlossen, PHP und MySQL zu updaten, also käme das infrage.

            Templates sind aber wohl kein Thema hier im Forum?

            Warum nicht?

            Kannst du mir ein geeignetes Forum für dieses Thema nennen? Bin Anfänger.

            echo "$verabschiedung $name";

            1. Moin!

              Templates sind aber wohl kein Thema hier im Forum?

              Warum nicht?

              Doch, aber da die Art, wie Templates konkret zu programmieren sind, immer explizit von der verwendeten Template-Engine abhängt, und diese wiederum von der Programmiersprache (wenngleich das Template-Format damit nicht grundsätzlich verbunden sein muß), gibt es kein sinnvolles Themengebiet "TEMPLATES". Allein die Vielfalt an Möglichkeiten (siehe http://de.wikipedia.org/wiki/Template) des Begriffs macht das schon unmöglich.

              Kannst du mir ein geeignetes Forum für dieses Thema nennen? Bin Anfänger.

              ...das ist schon durchgedrungen...

              - Sven Rautenberg

              --
              My sssignature, my preciousssss!
            2. echo $begrüßung;

              Templates sind aber wohl kein Thema hier im Forum?

              Nicht dass ich wüsste. Ich las schon des öfteren Beiträge, mit Fragen zum Thema, die auch beantwortet wurden. Es ist nur keine Technik mit der beginnende PHP-Programmierer bewusst arbeiten. Unbewusst arbeiten sie damit, weil PHP an sich schon ein Template-System ist, jedoch wird die oft propagierte Trennung von Eingabe-, Verarbeitungs und Ausgabe-Logik mangels besseren Wissens vernachlässigt.

              Kannst du mir ein geeignetes Forum für dieses Thema nennen? Bin Anfänger.

              (Die Ausrede, man sei Anfänger, wird gern benutzt, um irgendwelche Vorteile zu erlangen, die sich mir nicht erschließen. Ob jemand wenig Kenntnisse besitzt, merkt man meist schon an der Art der Fragestellung und dem Wissen bzw. Nichtwissen, das sich im Laufe des Thread herausstellt. Oft (nicht immer) ist so eine Aussage gleichzusetzen mit einem Nichtwirklichbeschäftigenwollen mit dem Thema, was bei mir gelegentlich die Antwortlust dämpft. Deswegen ist eine solche Aussage in meinen Augen weniger hilfreich als sich der sie verwendende erhofft. Aber das nur nebenbei.)

              Ein wohl recht beliebtes Templatesystem ist Smarty. Dazu gibt es sicher auch ein eigenes Forum. Mir persönlich gefällt diese Art von Template-System jedoch nicht sonderlich.

              Es gibt verschiedene Ansätze, die Trennung von Verarbeitung und Ausgabe anzugehen. Ein Ansatz ist, dass man die Ausgabelogik zur Ausgabe zählt. Wenn also x Datensätze auszugeben sind, wird die Schleife zum Ausgeben als Aufgabe des Template-Systems angesehen. Dafür finden sich dann Elemente (oder Nachbildungen davon) wie for-Schleifen im Template-System. Derjenige, der das Template schreibt, muss dann neben dem HTML (oder XML oder was auch immer) auch diese Elemente kennen und richtig einsetzen können.

              HTML_Template_IT geht den anderen Weg. Es kennt nur die Elemente Platzhalter und Block. Sämtliche Ausgabelogik steht im Programm. Ein Template-Schreiber für dieses System hat also deutlich weniger Elemente dazuzulernen.
              HTML_Template_Sigma basiert auf HTML_Template_IT und fügt zwei Funktionalitäten hinzu: Includes und Funktionsaufrufe. Für mein Verständnis ist das für ein Template-System ausreichend.

              Die Frage nach dem besseren System ist philosophischer Natur. Vermutlich gibt es ebenso viele Gründe für den einen Ansatz wie gegen den anderen und umgekehrt.

              Ein Template-System ist natürlich auch wieder ein Stück Code, das Zeit bei der Abarbeitung benötigt. Wenn man diese sparen möchte und trotzdem nicht auf PHP verzichten will, kann man auch gleich bei "reinem" PHP bleiben, vielleicht ergänzt um ein wenig Datenverwaltung. Außerdem spart man sich dabei das Hantieren mit RegExps. Hier ein Beispiel wie so etwas aussehen könnte (einsetzbar ab PHP4 (wegen Verwendung von Referenzen und statischen Variablen)):

              template.php

              <?php  
              /**  
               * data - kümmert sich um die Ausgabedatenhaltung  
               *  
               * schreibender Zugriff - Variante 1  
               *   data('placeholdername', 'value');  
               * schreibender Zugriff - Variante 2  
               *   $placeholder =& data('placeholdername');  
               *   $placeholder = 'value';  
               * lesender Zugriff  
               *   echo data('placeholdername');  
               *  
               * @param string/int $placeholder Name des Platzhalters  
               * @param mixed $value (optional) Wert für den Platzhalter  
               * @return mixed  Referenz auf Platzhalterwert  
               */  
              function &data($placeholder, $value = null) {  
                // Statische Variable. Behält ihren Inhalt auch bei mehrfachem Aufruf.  
                static $data = array();  
                
                // gegebenenfalls einen übergebenen Wert eintragen  
                if (!is_null($value))  
                  $data[$placeholder] = $value;  
                
                // als Leerstring anlegen, wenn placeholder nicht vorhanden ist.  
                if (!isset($data[$placeholder]))  
                  $data[$placeholder] = '';  
                
                // Referenz auf anfgeforderten Wert zurückgeben.  
                // Damit kann auch der Rest des Programmes den Wert direkt beeinflussen.  
                return &$data[$placeholder];  
              }  
                
              /**  
               * p - Platzhalterwert-Ausgabe  
               *  
               * @param string $placeholder Name des Platzhalters  
               * @return void  
               */  
              function p($placeholder) {  
                echo data($placeholder);  
              }  
              ?>
              

              Der verarbeitende Teil des Programms übergibt die auszugebenden Daten der Funktion data() zur Aufbewahrung, beispielsweise so:

              data('title', 'hello world');
                data('name', 'Welt');

              Das Template wird mit einem der include-Befehle eingeladen (oder auch direkt an Eingabe- und Verarbeitungsteil angehängt) und könnte so aussehen:

              <!DOCTYPE...>  
              <html>  
              <head>  
                <title><?php p('title') ?></title>  
              </head>  
              <body>  
                <p>Hallo <?php p('name')?>!</p>  
              </body>  
              </html>
              

              Dieses System ist für Projekte geeignet bei denen der Programmierer auch die Templates schreibt oder wenn der Template-Schreiber PHP-Grundkenntnisse hat (oder man ihm diese beibringen kann).

              Um wiederholte Daten ausgeben zu können, folgt hier noch eine Ergänzung. Die Funktion p() wurde erweitert und eine Funktion namens loop() kommt hinzu.

                
              /**  
               * p - Platzhalterwert-Ausgabe  
               *  
               * @param string $placeholder Name des Platzhalters  
               * @param boolean $global (optional) Loop ignorieren, globale Ausgabedaten verwenden  
               * @return void  
               */  
              function p($placeholder, $global = false) {  
                // Loop nicht ignoriert und Aufruf innerhalb eines Loops?  
                if (!$global and $loop = loop(false)) {  
                  $data =& data($loop);  
                  if (!is_array($data)) {  
                    // keine Loopdaten vorhanden  
                    echo '';  
                    return;  
                  }  
                  $record = current($data);  
                  echo isset($record[$placeholder]) ? $record[$placeholder] : '';  
                  return;  
                }  
                
                echo data($placeholder);  
              }  
                
              /**  
               * loop - startet einen Loop oder setzt den Loopdatenzeiger weiter  
               *  
               * Anwendungsbeispiel:  
               *   Datenverarbeitung:  
               *     $records =& data('records', array());  
               *     $records[] = array('col1' => 'value11', 'col2' => 'value12'); // ein Datensatz  
               *     $records[] = array('col1' => 'value21', 'col2' => 'value22'); // noch ein Datensatz  
               *   Ausgabe:  
               *     <table>  
               *     <?php while (loop('records')): ?>  
               *       <tr><td><?php p('col1');?></td><td><?php p('col2');?></td></tr>  
               *     <?php endwhile;?>  
               *     </table>  
               *  
               * nichtöffentliche Verwendung:  
               *   Wird loop(false) aufgerufen, wird der aktuelle Loopname oder null zurückgegeben  
               *  
               * @param string $loop Name des Loops  
               * @return boolean  true wenn Loopdaten vorhanden  
               */  
              function loop($loop) {  
                static $loopnamestack = array();  
                static $currentloopname = null;  
                
                // interne Nutzung: p() frag den aktuellen Loopnamen ab  
                if (!$loop)  
                  return $currentloopname;  
                
                // neuer Loop fängt an  
                if ($loop != $currentloopname) {  
                  // ggf. aktuellen Loopnamen sichern; neuen merken  
                  if ($currentloopname)  
                    $loopnamestack[] = $currentloopname;  
                  $currentloopname = $loop;  
                
                  // Loop-Daten vorbereiten  
                  $data =& data($loop);  
                  // kein Array => false => keine Schleife  
                  if (!is_array($data))  
                    return false;  
                  // leeres Array => false => keine Schleife  
                  return (boolean) reset($data);  
                }  
                // weiter im aktuellen Loop  
                else {  
                  $data =& data($loop);  
                  // kein Array => false => keine Schleife  
                  if (!is_array($data))  
                    return false;  
                  // Array-Ende => false => Schleifenende  
                  if (!next($data)) {  
                    // gesicherten Loopnamen ggf. wiederherstellen  
                    $currentloopname = array_pop($loopnamestack); // null wenn $loopnamestack leer ist  
                    return false;  
                  }  
                  return true;  
                }  
              }
              

              Man kann sogar Loops verschachteln, wie das folgende Anwendungsbeispiel zeigt.

              Datenverarbeitung:

              <?php  
              data('title', 'hello world'); // Variante 1  
              $name =& data('name');  
              // Variante 2  
              $name = 'Welt';  
                
              $dbdata =& data('dbdata', array());  
              $dbdata[] = array('name' => 'foo'); // ein Datensatz  
              $dbdata[] = array('name' => 'bar'); // noch ein Datensatz  
                
              data('loop', array(array(1), array(2), array(3)));  
              ?>
              

              Template:

              <!DOCTYPE...>  
              <html>  
              <head>  
                <title><?php p('title') ?></title>  
              </head>  
              <body>  
                <p>Hallo <?php p('name')?>!</p><!-- globaler Zugriff -->  
                
                <?php while (loop('loop')):?>  
                  <!-- numerisch indexierte Daten und globaler Zugriff aus einem Loop heraus -->  
                  <p>Loop <?php p(0)?> (<?php p('name', true)?>):</p>  
                  <?php while (loop('dbdata')):?>  
                    <p>Hallo <?php p('name')?>!</p>  
                  <?php endwhile; ?>  
                <?php endwhile; ?>  
                
                <p>Hallo <?php p('name')?>!</p><!-- wieder globaler Zugriff -->  
              </body>  
              </html>
              

              Es wäre auch möglich, dieses System als Klasse zu schreiben, was aber Mehraufwand beim Template-Schreiben bedeutet, da man dann entweder Objektmethoden ($template->methode()) oder Klassenmethoden (Template::methode()) statt einfacher Funktionsaufrufe (funktion()) notieren muss.

              Wenn du dich nun fragst, warum ich trotz meiner Abneigung gegen Code im Template den Nachmittag damit verbracht habe, solch ein System zu schreiben, dann versuche ich das so zu begründen: Man muss manchmal Kompromisse schließen. Dieses System habe ich mit dem Ziel entwickelt, geringen Aufwand für Abarbeitung durch die PHP-Maschine mit möglichst einfacher Template-Syntax zu verbinden. Letztere ist sogar im Rahmen der PHP-Möglichkeiten beliebig ausbaubar. (Habe ich etwa grade Smarty nacherfunden?)

              echo "$verabschiedung $name";

              Und wenn jemand Lust hat, einen Feature-/Tipps&Tricks-/wasAnderes-Artikel mit diesem Template-System schreiben, nur zu ... :-)