Ankündigung

Einklappen
Keine Ankündigung bisher.

Zeichenkette aus DB durch bestimmte Wörter ersetzen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Zeichenkette aus DB durch bestimmte Wörter ersetzen

    Hallo zusammen,

    ich verzweifel gerade bei einer, sicherlich recht einfachen Sache, für jemanden der mit PHP fitter ist als ich.

    Ich habe zu einer Person Merkmale als Zahl in meiner DB und der User Tabelle hinterlegt - Schema 1;7;4;10;11;
    Diese Werte werden beim eintragen nicht sortiert.

    Es gibt eine weitere Tabelle in meiner DB (MERKMALE), die IDs und die Bezeichnung dieses Merkmals enthält.
    1 Auto
    2 Baum
    3 Haus
    4 Boot
    5 Drachen
    6 Schule
    7 Teil
    8 Maske
    9 Edding
    10 Wort
    11 Farbe
    12 Scheune
    Ich habe dies so gelöst, damit ich die Merkmale später beliebig erweitern kann, und dann eben IDs automatisch zugefügt werde und ich nur die Bezeichnung eintragen muss.
    Bis dato bin ich in meinem kleinen Test-Projekt damit gut zu Rande gekommen und es hat überall alles funktioniert, wo ich nur die Zahlen abrufe und/oder verarbeite.

    Nun habe ich auf einer Seite das Bedürfnis, die Werte/Merkmale zur Person auszulesen und dann nicht die ID/Zahl, sondern das entsprechende Wort zurück zu geben.

    Ich habe mir dazu bereits schon mal eine Funktion geschrieben, die ich genutzt habe. Man war ich stolz, hat MICH viel überlegung gekoste, weil ich auch hier nicht auf die Lösung kam...

    Meine Werte wurden von 1;4;8; in mein gewünschtes Format Auto, Boot, Maske umgewandelt.
    Sprich kommagetrennte Worte und hinter dem letzen Wort kein Komma und Leerzeichen mehr.

    Nur leider geht das ganze nun in die Brüche, wo ich mit den IDs im zweistelligen Bereich angelangt bin.
    Nun wird nämlich aus der 10, ein Auto0 und aus einer 11 wird AutoAuto.


    Hier meine Funktion

    PHP-Code:
    function id_zu_namen($intxt){

                global 
    $db_pre;

                
    $sql "SELECT * FROM merkmale ORDER BY id ASC";
                
    $result $db_pre->query($sql) OR die(mysqli_error());

                
    $list = array();

                while (
    $row $result->fetch_assoc()) {
                    
    $list[] = $row;
                    } 
                    
    $var_name = array();
                    foreach (
    $list as $i => $record) {
                        
    $var_name[] = $record['bezeichnung'];
                    }  
                    
    $var_id = array();
                    foreach (
    $list as $i => $record) {
                        
    $var_id[] = $record['id'];
                    } 
                    
    $intxt str_replace($var_id$var_name$intxt);
                    
    $intxt str_replace(";",", ",substr($intxt,0,-1));
                    return 
    $intxt;

                } 
    Ich habe schon sehr viel probiert. Habe versucht meinen String als Array zu konvertieren und dann mit preg_replace() oder array_replace() zu hantieren. Leider bin ich bis dato zu keinem Ergebnis gekommen.

    Hat dazu noch jemand eine brauchbare Idee?

    Vielen Dank für eure Hilfe

  • #2
    Die Tabelle ist fehlerhaft. Pro Spalte sollte nicht mehr als ein Wert drin stehen.

    Du bräuchtest 3 Tabellen:

    user - id, name
    attribute - id, name
    user_attribute - user_id, attribute_id

    Desweiteren sollte kein SELECT * verwendet werden und "global" ist böse.

    Kommentar


    • #3
      Schema 1;7;4;10;11;
      Falsche Datenhaltung. Kannst du das ändern? Dann mach es gelich. Leg eine eigene Tabelle an, in der du diese n:m Beziehungen speicherst.

      Schau mal hier: http://www.sqldocu.com/nine/relationship.htm#emzuen
      The string "()()" is not palindrom but the String "())(" is.

      Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
      PHP.de Wissenssammlung | Kein Support per PN

      Kommentar


      • #4
        Dein Datenmodell ist falsch, du verkomplizierst Dir die ganze Sache. (Wenn ich das jetzt richtig verstanden habe)

        Du müsstest 3 Tabellen haben, einerseits User, dann Merkmale und dann User_Merkmale. Die dritte ist eine Kreuztabelle in welcher du pro User und Merkmal einen Eintrag machst. Dann hast du all die Sorgen los.

        Ausserdem solltest du global nicht verwenden und die Datenbankverbindung als Parameter an eine Funktion übergeben.

        Kommentar


        • #5
          Nun wie weit die Normalisierung der Tabellen getrieben wird ist abhängig vom speziellen Anwendungsfall. Ich gehe mal jetzt davon aus crashy1984 hat sehr gute Gründe nicht zu normalisieren.
          Zum Problem:
          Ich würde mir die Merkmale ein mal holen und in ein Array mit id => Merkmal packen (Vermute mal diese ist nicht allzu groß).
          Von deiner Id-Liste brauchst du ein Array und mit array_intersect_key mit folgenden implode bekommst du deine Liste.
          PHP-Code:
          $id array_filter(explode(';',$idList));
          $descriptions array_intersect_key($allDescriptions,array_flip($id));
          $list implode(',',$descriptions); 
          Das array_filter ist notwendig um kein leeres Element zu erhalten (oder das letzte ; bleibt immer weg).

          Kommentar


          • #6
            wow, Danke Leute - ganz ehrlich für die rege Teilnahme an meinem Problemchen.

            Ich habe versucht mich mit PHP und MySQL durch viele Bücher, Online-Inhalte & Co. zu belesen und festgestellt, dass dies für MICH zu theoretisch ist. Daher habe ich den Weg Learning-by-Doing eingeschlagen.

            Natürlich ist mit der Begriff Normalisieren nicht fremd. Ich habe den Weg dazu hier bloß nicht gewählt weil ich sonst die "Befürchtung" habe, dass die weggelassene Tabelle "user_merkmale" einfach viel zu groß werden würde.
            Wenn man mal davon ausgeht das später mehr als 10.000 User enthalten sein könnten, die dann N Merkmale haben (derzeit gibt es 18 verschiedene), wird die Tabelle doch exorbitant groß... also bei 10.000 Usern wären das max 180.000 Einträge. Da weiß ich nun wirklich nicht, wie weit das nachher noch Sinn macht?!


            Zitat von hellbringer Beitrag anzeigen
            Desweiteren sollte kein SELECT * verwendet werden und "global" ist böse.
            In diesem Select sind es ja nur 2 Spalten (ID und Bezeichnung). Sollte man hier trotzdem dann nicht per * sondern per Spaltenname angeben was man möchte? Ich dachte das wenn ich aus der Tabelle wirklich alles nehmen möchte, das * gängig wäre?
            Wenn man das nicht macht, magst du mir verraten warum nicht?

            Das "global" muss ich in der Funktion nutzen, da ich sonst innerhalb meiner Funktion keinen DB Connect erhalte. Oder sollte ich den Connect lieber dort ausschreiben? denn eigentlich habe ich mir für den Connect eine Funktion geschrieben.

            ​​​​​​​

            Zitat von jspit Beitrag anzeigen
            Nun wie weit die Normalisierung der Tabellen getrieben wird ist abhängig vom speziellen Anwendungsfall. Ich gehe mal jetzt davon aus crashy1984 hat sehr gute Gründe nicht zu normalisieren.
            Zum Problem:
            Ich würde mir die Merkmale ein mal holen und in ein Array mit id => Merkmal packen (Vermute mal diese ist nicht allzu groß).
            Von deiner Id-Liste brauchst du ein Array und mit array_intersect_key mit folgenden implode bekommst du deine Liste.
            PHP-Code:
            $id array_filter(explode(';',$idList));
            $descriptions array_intersect_key($allDescriptions,array_flip($id));
            $list implode(',',$descriptions); 
            Das array_filter ist notwendig um kein leeres Element zu erhalten (oder das letzte ; bleibt immer weg).
            ich werde das mal testen.

            Kommentar


            • #7
              wird die Tabelle doch exorbitant groß... also bei 10.000 Usern wären das max 180.000 Einträge. Da weiß ich nun wirklich nicht, wie weit das nachher noch Sinn macht?!
              Wenn es 180 Milllionen sind dann reden wir weiter. Und genau dann macht es Sinn! Wenn du es nicht so machst ist es eher so, das du dann die Probleme bekommst. Eine Datenbank kann Das wofür Sie geschaffen wurde am Besten machen, wenn man die Daten "richtig" hält.

              In diesem Select sind es ja nur 2 Spalten (ID und Bezeichnung). Sollte man hier trotzdem dann nicht per * sondern per Spaltenname angeben was man möchte? Ich dachte das wenn ich aus der Tabelle wirklich alles nehmen möchte, das * gängig wäre?
              Nein, ohne * , siehe zB:

              https://www.pg-forum.de/viewtopic.php?f=66&t=4309

              https://php-de.github.io/jumpto/code-smells/#select-all
              The string "()()" is not palindrom but the String "())(" is.

              Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
              PHP.de Wissenssammlung | Kein Support per PN

              Kommentar


              • #8
                Zitat von crashy1984 Beitrag anzeigen
                Das "global" muss ich in der Funktion nutzen, da ich sonst innerhalb meiner Funktion keinen DB Connect erhalte.
                Dafür wurden Funktionsparameter erfunden. global brauchst du niemals nie. Das sind Altlasten aus der Frühgeburt von PHP.

                Kommentar


                • #9
                  Zitat von crashy1984 Beitrag anzeigen
                  wären das max 180.000 Einträge.
                  Dafür wurden Datenbanken entwickelt um aus grossen Datenmengen effizient rauszufiltern was man braucht. Ist also kein Problem wenn das auch mal 180 Mio. werden.


                  Zitat von crashy1984 Beitrag anzeigen
                  Wenn man das nicht macht, magst du mir verraten warum nicht?
                  Code:
                  SELECT * FROM myTable
                  Kannst du mir sagen welchen Spalten ausgegeben werden?


                  Zitat von crashy1984 Beitrag anzeigen
                  Das "global" muss ich in der Funktion nutzen,
                  Übergib es einfach als Parameter:
                  PHP-Code:
                  function id_zu_namen($intxt$db_pre){ 
                  Bei Aufruf der Funktion muss das dann natürlich mit übergeben werden. so macht es Die Mysqli Funktion bei prozeduraler Schreibweise auch.

                  Kommentar


                  • #10
                    Zitat von jspit Beitrag anzeigen
                    Nun wie weit die Normalisierung der Tabellen getrieben wird ist abhängig vom speziellen Anwendungsfall. Ich gehe mal jetzt davon aus crashy1984 hat sehr gute Gründe nicht zu normalisieren.
                    Zum Problem:
                    Ich würde mir die Merkmale ein mal holen und in ein Array mit id => Merkmal packen (Vermute mal diese ist nicht allzu groß).
                    Von deiner Id-Liste brauchst du ein Array und mit array_intersect_key mit folgenden implode bekommst du deine Liste.
                    PHP-Code:
                    $id array_filter(explode(';',$idList));
                    $descriptions array_intersect_key($allDescriptions,array_flip($id));
                    $list implode(',',$descriptions); 
                    Das array_filter ist notwendig um kein leeres Element zu erhalten (oder das letzte ; bleibt immer weg).
                    habe es nun so versucht, bekomme aber die "falschen" Werte/Worte geliefert.

                    Meine Tabelle:
                    tabelle.PNG


                    PHP-Code:

                    $intxt 
                    ="1;2;;14;7;15;";   //Beispielwert sollte ergeben: Akt, Teilakt, Fernsehen, Fashion, Dessous


                    $sql "SELECT id, bezeichnung FROM merkmale ORDER BY id ASC";
                                
                    $result $db_pre->query($sql) OR die(mysqli_error());

                                
                    $list = array();

                                while (
                    $row $result->fetch_assoc()) {
                                    
                    $list[] = $row;
                                    }
                                    
                    $var_name = array();
                                    foreach (
                    $list as $i => $record) {
                                        
                    $var_name[] = $record['bezeichnung'];
                                    }  
                                    
                    $var_id = array();
                                    foreach (
                    $list as $i => $record) {
                                        
                    $var_id[] = $record['id'];
                                    }


                                    
                    $intxt array_filter(explode(';',$intxt));
                                    
                    $intxt array_intersect_key($var_name,array_flip($intxt));
                                    
                    $intxt implode(', ',$intxt);  

                                    echo 
                    $intxt//ergibt leider falsch: Teilakt, Bademode, verdeckter Akt, Theater, Promotion 
                    ich muss dazu sagen, das ich es auch nicht wirklich verstanden habe.
                    Du schreibt vorweg, dass ich die Merkmale vorab holen möge und dann ID => Merkmal zuweisen soll. das habe ich nicht hinbekommen und auch nichts gefunden, was mit dazu nun Erleuchtung brachte. Ich weiß das es darum geht dem Arry den schlüssel und den wert zu nennen, doch weiß ich leider nicht wie genau?!

                    Kommentar


                    • #11
                      Zitat von protestix Beitrag anzeigen
                      Dafür wurden Datenbanken entwickelt um aus grossen Datenmengen effizient rauszufiltern was man braucht. Ist also kein Problem wenn das auch mal 180 Mio. werden.



                      Code:
                      SELECT * FROM myTable
                      Kannst du mir sagen welchen Spalten ausgegeben werden?
                      bei der Abfrage weiß ich es nicht, da ich die Tabelle myTable ja nicht kenne. Bei meiner Tabelle "merkmale" werden die Spalten "id" und "bezeichnung" ausgegeben, mehr steht ja auch nicht drin.


                      Zitat von hausl Beitrag anzeigen

                      Wenn es 180 Milllionen sind dann reden wir weiter. Und genau dann macht es Sinn! Wenn du es nicht so machst ist es eher so, das du dann die Probleme bekommst. Eine Datenbank kann Das wofür Sie geschaffen wurde am Besten machen, wenn man die Daten "richtig" hält.
                      Nochmal zum Thema normalisieren habe ich nun ein anderes Problem:

                      Ich über gebe dann die Werte an die Tabelle "users" mittels "INSERT INTO users..." bei einem neuen User, oder eben per "UPDATE user....", wenn der User schon bestand.
                      Somit habe ich den aktuellen Wert in die Spalte "merkmale" schreiben lassen.

                      Wenn ich diesen Wert nun auslagern würde in eine andere Tabelle z.B. "users_merkmale", muss ich meinem Statement ja sicherlich so was zufügen wie "INSERT INTO user_merkamle" und eine Art "UPDATE users_merkmale.....".
                      Nur wenn von dem User schon Daten der Tabelle "merkmale" enthalten sind, wie mache ich das? Muss ich vorher alle enthaltenen Daten des Users löschen um diese dann neu schreiben zu lassen, sobald eine Änderung an den Daten des User erfolgt?




                      Kommentar


                      • #12
                        Zitat von crashy1984 Beitrag anzeigen
                        Nur wenn von dem User schon Daten der Tabelle "merkmale" enthalten sind, wie mache ich das? Muss ich vorher alle enthaltenen Daten des Users löschen um diese dann neu schreiben zu lassen, sobald eine Änderung an den Daten des User erfolgt?
                        Das wäre die radikale (und unschöne) Methode. Idealerweise programmierst du dein Frontend so, dass du genau weisst welche Merkmale gelöscht wurden und welche hinzukommen. Dann kannst du spezifisch löschen und spezifisch hinzufügen. UPDATE brauchst du da nicht. Nur INSERT und DELETE.

                        Kommentar


                        • #13
                          habe es nun so versucht, bekomme aber die "falschen" Werte/Worte geliefert.
                          Zur Abfrage über mehr Tabellen verwendet du dann einen JOIN.


                          Ich über gebe dann die Werte an die Tabelle "users" mittels "INSERT INTO users..." bei einem neuen User, oder eben per "UPDATE user....", wenn der User schon bestand
                          Dafür gibt es (MySQL / MariaSQL) eigentlich https://mariadb.com/kb/en/library/in...te-key-update/


                          Nur wenn von dem User schon Daten der Tabelle "merkmale" enthalten sind, wie mache ich das? Muss ich vorher alle enthaltenen Daten des Users löschen um diese dann neu schreiben zu lassen, sobald eine Änderung an den Daten des User erfolgt?
                          Nein, du ergänzt in der Zwischentabelle nur das neue Merkmal. Oder ich hab die Frage nicht verstanden.


                          Schau dir doch das oben von mir verlinkte Beispiel mit den Raumschiffen an. http://www.sqldocu.com/nine/relationship.htm#emzuen Da sieht man das schön. Eine Person kann mehr Schiffe haben und jedes Schiff kann mehr Personen haben. Ganz wie bei deinen Merkmalen. Jedes Merkmal mehr Personen und jede Person mehr Merkmale. Das nennt sich dann eben n:m Beziehung.
                          The string "()()" is not palindrom but the String "())(" is.

                          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                          PHP.de Wissenssammlung | Kein Support per PN

                          Kommentar


                          • #14
                            Zitat von jonas3344 Beitrag anzeigen

                            Das wäre die radikale (und unschöne) Methode. Idealerweise programmierst du dein Frontend so, dass du genau weisst welche Merkmale gelöscht wurden und welche hinzukommen. Dann kannst du spezifisch löschen und spezifisch hinzufügen. UPDATE brauchst du da nicht. Nur INSERT und DELETE.
                            also ich meine mit dem erst alles löschen und dann einfügen, nur die tabelle user_merkmale und auch nur die userspezifischen Inhalte, nicht die ganzen inhalte der user tabelle.

                            heißt für mich wenn ich irgendwo abfrage nutze ich:

                            Code:
                            $sql = SELECT merkmale_id FROM user_merkmale WHERE user_id = "$user_id";
                            habe dann die Werte aber wieder als Zahl vorliegen.
                            Wie mache ich dann aus den Ziffern wieder meine benötigte Zeichenkette von "xx, test, blabluub" (Kommagetrennte Werte)


                            beim speichern bzw. Absenden des Formulars der neuen Daten:
                            PHP-Code:
                            DELETE FROM user_merkmale WHERE user_id "$user_id";
                            INSERT INTO user_merkmale (user_idmerkmale_idVALUES $_POST['user_id], $wert_merkmaleID 
                            da stoße ich an das nächste Problem:

                            die Werte der Merkmale, werden im Frontend via Radio-button gesetzt und auch abgefragt.
                            Abfrage:
                            PHP-Code:

                            $sql 
                            "SELECT * FROM model WHERE (id = '"$_GET['edit'] ."' AND user_id = '"$_SESSION['userID'] ."')";
                                                
                            $result $db_pre->query($sql) OR die(mysqli_error());
                                                
                            $row $result->fetch_assoc();

                                                
                            // Bereiche Array
                                                
                            $bereiche_arr explode(";",$row['aufnahmebereiche']);
                                                
                            $bereiche_arr clean_array($bereiche_arr);


                            $sql_aufnahmebereiche "SELECT id, bezeichnung FROM aufnahmebereiche ORDER BY bezeichnung ASC";
                                                                    
                            $result_aufnahmebereiche $db_pre->query($sql_aufnahmebereiche) OR die(mysqli_error());

                                                                    echo 
                            "<div style="text-align:center;">";
                                                                    if(
                            $result_aufnahmebereiche->num_rows 0)
                                                                        {
                                                                            while(
                            $row_aufnahmebereiche $result_aufnahmebereiche->fetch_assoc())
                                                                                {

                                                                                  echo 
                            "<div class="aufnahmebereiche_liste">

                                                                                            <div class="
                            aufnahmebereiche_liste_bezeichnung">"$row_aufnahmebereiche['bezeichnung'] ."
                                                                                            <!-- .slideThree -->
                                                                                            <div class="
                            slideThree">  
                                                                                              <input "
                            ; if(in_array($row_aufnahmebereiche['id'], $bereiche_arr)) { echo "checked="checked""; } echo " type="checkbox" value="". $row_aufnahmebereiche['id'] ."" id="slideThree". $row_aufnahmebereiche['id'] ."" name="aufnahmebereiche[]">
                                                                                              <label for="
                            slideThree". $row_aufnahmebereiche['id'] .""></label>
                                                                                            </div>
                                                                                            <!-- end .slideThree -->
                                                                                            </div>
                                                                                        </div>"
                            ;                                            
                                                                                }
                                                                        } 
                            Schreiben entsprechend dem VALUE $aufnahmebereiche[]

                            Kommentar


                            • #15
                              habe dann die Werte aber wieder als Zahl vorliegen.
                              Wie mache ich dann aus den Ziffern wieder meine benötigte Zeichenkette
                              JOIN .. Hatte ich schon erwähnt.

                              Sowas.. hier getippt, musst du anpassen.
                              Code:
                              SELECT
                                u.name, m.merkmal, ... was immer du im Ergebnis haben willst
                              
                              FROM
                                user_merkmale m
                              
                              INNER JOIN
                                user u ON u.id = m.user_id
                              
                              WHERE
                                user_id = 123
                              The string "()()" is not palindrom but the String "())(" is.

                              Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                              PHP.de Wissenssammlung | Kein Support per PN

                              Kommentar

                              Lädt...
                              X