Enrico: Fehler bei zu kürzendem String

Hallo,

ich habe auf unserer Seite einen Abschnitt, in dem ich die derzeitig im Warenkorb abgelegten Artikel aufzähle.

Da hierbei nur eine bestimmte Breite zur Verfügung steht, kürze ich die Ausgabe, falls erforderlich, und hänge drei Punkte als Auslassungszeichen an.

Desweiteren kennzeichne ich Artikel, die nur an Personen ab 18 verkauft werden dürfen, im Artikelnamen mit der Raute, die bei der Ausgabe natürlich nicht angezeigt werden soll.

Hier der relevante Code:

  
if (isset ($_SESSION["Warenkorb"]))  
{  
   $w = count ($_SESSION["Warenkorb"]);  
  
   for ($x = 0; $x < $w; $x++)  
   {  
      if (substr ($_SESSION["Warenkorb"][$x]["Artikel"], 0, 1) == "#")  
         $Artikel = '<span class="Ab18">' . $_SESSION["Warenkorb"][$x]["Menge"] . "x " . substr ($_SESSION["Warenkorb"][$x]["Artikel"], 1, strlen ($_SESSION["Warenkorb"][$x]["Artikel"])) . "</span>";  
      else  
         $Artikel = $_SESSION["Warenkorb"][$x]["Menge"] . "x " . $_SESSION["Warenkorb"][$x]["Artikel"];  
  
      if (strlen ($Artikel) > 22)  
      {  
         if (substr ($Artikel, 22, 1) == " ")  
            $Laenge = 19;  
         else  
            $Laenge = 20;  
      }  
      else  
         $Laenge = strlen ($Artikel);  
  
      echo '<a class="Liste">' . substr ($Artikel, 0, $Laenge) . "..." . "</a>";  
  
      if ($x < $w - 1)  
         echo "<br>";  
   }  
}  

Was ich jetzt aber nicht verstehe, ist, dass mir Artikel mit dem Kennzeichen "#" im Artikelnamen nur mit der Menge als Zahl, aber ohne das "x", sowie den drei Punkten, angezeigt werden, beispielsweise "1...", alle anderen Artikel hingegen vollständig in der gekürzten Form, beispielsweise "1x Mit Eisenplatten ...".

Wo liegt der Fehler?

Vielen Dank für eure Hilfe und Gruß,
Enrico

  1. Moin,

    if (substr ($_SESSION["Warenkorb"][$x]["Artikel"], 0, 1) == "#")

    um auf das erste Zeichen eines Strings zuzugreifen, würde ich nicht die Funktion substr() bemühen, sondern den Zugriff im Array-Stil, etwa so:

    if ($_SESSION["Warenkorb"][$x]["Artikel"][0]=="#")

    $Artikel = '<span class="Ab18">' . $_SESSION["Warenkorb"][$x]["Menge"] . "x " . substr ($_SESSION["Warenkorb"][$x]["Artikel"], 1, strlen ($_SESSION["Warenkorb"][$x]["Artikel"])) . "</span>";

    Hier ist substr() zwar richtig, aber warum machst du dir die Mühe, die gewünschte Länge noch extra auszurechnen (und dann auch noch falsch/zu lang)? Du willst den String ab Offset 1 bis zum Ende, also lass doch den length-Parameter einfach weg.

    Was ich jetzt aber nicht verstehe, ist, dass mir Artikel mit dem Kennzeichen "#" im Artikelnamen nur mit der Menge als Zahl, aber ohne das "x", sowie den drei Punkten, angezeigt werden, beispielsweise "1...", alle anderen Artikel hingegen vollständig in der gekürzten Form, beispielsweise "1x Mit Eisenplatten ...".
    Wo liegt der Fehler?

    Kann ich nicht auf Anhieb erkennen, dafür ist mir dein PHP-Code im ersten Moment zu unübersichtlich. Wie sieht das erzeugte HTML aus? Versuche von dort aus Rückschlüsse auf das falsche Verhalten des PHP-Codes zu ziehen.

    Ciao,
     Martin

    --
    F: Was ist eigentlich aus deinem schlimmen Durchfall geworden?
    A: Mein Arzt hat mir Valium verschrieben.
    F: Und das hilft?
    A: Naja, ich mach mir immer noch in die Hose. Aber inzwischen ist es mir egal.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Hallo Martin,

      danke für Deine schnelle Antwort.

      Ist der Zugriff auf ein bestimmtes Zeichen im Array-Stil schneller als substr?
      Kürzer ist der Code allemal, was evtl. ein kleines Quentchen an Performance-Gewinn bedeutet.

      Der html-Code im Browser sieht wie folgt aus:

        
      <a class="Liste"><span class="Ab18">1...</a><br>  
      <a class="Liste">1x Mit Eisenplatten ...</a><br>  
      <a class="Liste">1x Mittelbraune Lede...</a>  
      
      

      Warum ignoriert mein php-Code die Ausgabe des schliessenden span-Tags?

      Den Session-Warenkorb habe ich zu Testzwecken fest definiert:

        
      $_SESSION["Warenkorb"][0]["Bild"]    = "GewandungMuetzen1";  
      $_SESSION["Warenkorb"][0]["Artikel"] = "#Mittelalter Langgürtel mit Greif und Löwenmotiv";  
      $_SESSION["Warenkorb"][0]["Farbe"]   = "Schwarz";  
      $_SESSION["Warenkorb"][0]["Groesse"] = "M";  
      $_SESSION["Warenkorb"][0]["Preis"]   = "34.90";  
      
      

      Die (warum falsche/zu lange?) Längenberechnung habe ich jetzt rausgenommen, am Endergebnis ändert sich aber leider nichts:

        
      $Artikel = '<span class="Ab18">' . $_SESSION["Warenkorb"][$x]["Menge"] . "x " . substr ($_SESSION["Warenkorb"][$x]["Artikel"], 1) . "</span>";  
      
      

      Gruß,
      Enrico

      1. Hi,

        Ist der Zugriff auf ein bestimmtes Zeichen im Array-Stil schneller als substr?
        Kürzer ist der Code allemal, was evtl. ein kleines Quentchen an Performance-Gewinn bedeutet.

        etwas schneller ist es möglicherweise; ich vermute(!), dass ein simpler Datenzugriff schneller ist als ein Funktionsaufruf. Der Performancegewinn dürfte aber eher akademisch sein und im Rauschen untergehen. Allerdings ist es IMO übersichtlicher zu lesen.

        Der html-Code im Browser sieht wie folgt aus:

        <a class="Liste"><span class="Ab18">1...</a><br>

        <a class="Liste">1x Mit Eisenplatten ...</a><br>
        <a class="Liste">1x Mittelbraune Lede...</a>

          
        Okay, die Daten fehlen also schon im Quellcode. Ich wollte sichergehen, dass sie nicht aufgrund eines HTML-Fehlers oder einer bestimmten CSS-Regel bloß einfach nicht angezeigt werden.  
          
        
        > Warum ignoriert mein php-Code die Ausgabe des schliessenden span-Tags?  
          
        Gute Frage. Nächste Frage?  ;-)  
          
        Ich greife deinen ursprünglichen Code hier nochmal auf, weil du da einen kapitalen Bock drin hast, den ich jetzt erst sehe.  
          
        
        > ~~~php
        
              if (substr ($_SESSION["Warenkorb"][$x]["Artikel"], 0, 1) == "#")  
        
        >          $Artikel = '<span class="Ab18">' . $_SESSION["Warenkorb"][$x]["Menge"] . "x " . substr ($_SESSION["Warenkorb"][$x]["Artikel"], 1, strlen ($_SESSION["Warenkorb"][$x]["Artikel"])) . "</span>";  
        >       else  
        >          $Artikel = $_SESSION["Warenkorb"][$x]["Menge"] . "x " . $_SESSION["Warenkorb"][$x]["Artikel"];  
        >   
        >       if (strlen ($Artikel) > 22)  
        >       {  
        >          if (substr ($Artikel, 22, 1) == " ")  
        >             $Laenge = 19;  
        >          else  
        >             $Laenge = 20;  
        >       }  
        >       else  
        >          $Laenge = strlen ($Artikel);  
        >   
        >       echo '<a class="Liste">' . substr ($Artikel, 0, $Laenge) . "..." . "</a>";
        
        

        Du betrachtest hier strlen($Artikel), nachdem du diesen String komplett als HTML-Code zusammengebaut hast. Die öffnenden und schließenden span-Tags, die zusammen 21+5 Zeichen ausmachen, gehen also voll in die Länge mit ein. Also trifft die Abfrage auf strlen()>22 bei Ab18-Artikeln in jedem Fall zu, und du schneidest nach 22 Zeichen ab. Übrig bleibt das öffnende Tag (21 Zeichen) und das erste Zeichen des Nutzinhalts (die erste Ziffer der Mengenangabe). Das beantwortet wohl deine obige Frage.

        Was lernen wir daraus? - Genau, jedwede Verarbeitung (in diesem Fall das Kürzen der Einträge) sollte auf den Rohdaten passieren, nicht auf dem generierten Ausgabe-Code.

        Andere Frage: Warum sind Ab18-Einträge nicht verlinkt? Klar, weil's dein PHP-Code so erzeugt. Aber ist das Absicht?

        Die (warum falsche/zu lange?) Längenberechnung habe ich jetzt rausgenommen

        Warum falsch? Weil du die gesamte Stringlänge angibst, aber vorn schon ein Zeichen weglassen willst. Du "bestellst" den String also um ein Zeichen zu lang. Das macht nichts, weil strlen() nicht über das String-Ende hinaus arbeitet, aber es ist dennoch ein Logikfehler.

        Ciao,
         Martin

        --
        Dem Philosoph ist nichts zu doof.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hallo,

          Andere Frage: Warum sind Ab18-Einträge nicht verlinkt? Klar, weil's dein PHP-Code so erzeugt. Aber ist das Absicht?

          sorry, ich habe wohl Gespenster gesehen. Vergiss die Anmerkung einfach. ;-)

          Schönes Wochenende,
           Martin

          --
          "Mutti, hier steht, das Theater sucht Statisten. Was sind Statisten?" - "Das sind Leute, die nur rumstehen und nichts zu sagen haben." - "So wie Papa?"
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        2. Hallo Martin,

          nachdem du diesen String komplett als HTML-Code zusammengebaut hast

          Menschenskinder! Oftmals sind es so dermaßen banale, kleine Fehler, die einem ein gewünschtes Ergebnis verhageln, dass man auf die ersten 1, 2, 3... Blicke gar nicht dahinterkommt.

          Jetzt klappt es! :-)

          Besten Dank für Deine Hilfe.

          Gruß,
          Enrico

          1. Tach!

            Menschenskinder! Oftmals sind es so dermaßen banale, kleine Fehler, die einem ein gewünschtes Ergebnis verhageln, dass man auf die ersten 1, 2, 3... Blicke gar nicht dahinterkommt.

            Deswegen macht man ja auch Kontrollausgaben mit var_dump(). Du willst Daten verarbeiten, also kontrolliere die Eingabedaten und nach einer anscheinend nicht richtig arbeitenden Funktion deren Ausgabedaten.

            dedlfix.

            1. Moin,

              hier ein lügendes Beispiel:

              $str = "Gürtel";  
              echo $str." ist ".strlen($str)." Zeichen lang";  
              
              

              Ausgabe: Gürtel ist 7 Zeichen lang

              Also besser mb_strlen und mb_substr verwenden.

              Gast

  2. Hi,

    Desweiteren kennzeichne ich Artikel, die nur an Personen ab 18 verkauft werden dürfen, im Artikelnamen mit der Raute

    Entwerfe doch erst mal ein vernünftiges Datenmodell, anstatt so einen Unfug zu betreiben.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hallo ChrisB,

      Entwerfe doch erst mal ein vernünftiges Datenmodell, anstatt so einen Unfug zu betreiben.

      Sicher ist das nur ein optischer Gimmick, aber ich möchte die Ausgabe so haben.

      Die Session-Struktur habe ich nur aus der alten Version übernommen, final wird sie auch anders aufgebaut sein.

      Gruß,
      Enrico

      1. Hi,

        Entwerfe doch erst mal ein vernünftiges Datenmodell, anstatt so einen Unfug zu betreiben.

        Sicher ist das nur ein optischer Gimmick, aber ich möchte die Ausgabe so haben.

        Das bezog sich nicht auf das optische Gimmick, sondern darauf, wie du die „über Achtzehn”-Angebote kennzeichnest.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Hallo ChrisB,

          Das bezog sich [...] darauf, wie du die "über Achtzehn"-Angebote kennzeichnest.

          Wie würdest Du es anders machen?

          Ich finde ein simples Kennzeichen nicht "verwerflich".

          Gruß,
          Enrico

          1. Hallo,

            Das bezog sich [...] darauf, wie du die "über Achtzehn"-Angebote kennzeichnest.
            Wie würdest Du es anders machen?

            besser. ;-)

            Ich finde ein simples Kennzeichen nicht "verwerflich".

            Ich auch nicht. Aber die Ab18-Kennzeichnung hat nichts mit dem Namen zu tun, sondern ist eine eigenständige Information. Also sollte sie auch nicht im Namen stecken, sondern in einer eigenen Spalte. In einer Datenbank wäre das _ein_ Aspekt dessen, was man als Normalisierung bezeichnet.

            Die einzige "Entschuldigung" für dein bisheriges Vorgehen wäre, dass du die Daten aus einer externen Quelle bereits so angeliefert bekommst.

            Ciao,
             Martin

            --
            Theorie ist, wenn jeder weiß, wie's geht, und es geht trotzdem nicht.
            Praxis ist, wenn's geht, und keiner weiß warum.
            Bei uns sind Theorie und Praxis vereint: Nichts geht, und keiner weiß warum.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(