php.de

Zurück   php.de > php.de Intern > Wiki Diskussionsforum > Tutorials

Tutorials Hier findest Du Tutorials, welche nach und nach ein fertiges Script ergeben. Sehen, lernen & verstehen!

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 13.08.2005, 10:48  
Erfahrener Benutzer
 
Registriert seit: 21.05.2008
Beiträge: 387
MrNiceGuy befindet sich auf einem aufstrebenden Ast
Standard "BB-Code" - Lösungsansatz bei Verschachtelung

Hallo!

Dieses Tutorial soll nicht als Ersatz für das bestehende BB-Code-Tutorial dienen, sondern lediglich eine stetig auftauchende Problematik im Bereich der BB-Codes behandelt und einen Lösungsansatz bietet. Deswegen werde ich hier auch nicht weiter auf alle möglichen BB-Codes eingehen, die man nutzen könnte, sonder - damit es schön einfach ist - lediglich ein Beispiel anhand des 'b'-BB-Code-Tags ansprechen. Der Quelltext kann logischerweise an andere BB-Codes angepasst werden bzw. auch verallgemeinert werden, sollte dies nötig sein. Die Problematik, die ich meine: Verschachtelte BB-Codes.

Es ist leider so, dass mit dem normalen Befehl:

PHP-Code:
<?php
/* ... */
$text preg_replace ('/\[b\](.*)\[\/b\]/Us''[b]\\1[/b]'$text);
/* ... */
?>
bei folgendem Inhalt von $text:

Code:
Dies ist ein Test mit verschachtelten BB-Codes. 


das Ergebnis so aussieht:

Code:
Dies ist ein Test mit verschachtelten BB-Codes. 


Ansich ist das vielleicht nicht immer ein Problem, aber man kann diese Problematik der fehlerhaften BB-Codes leicht umgehen. Mich persönlich störte diese Problematik insbesondere bei fehlerhaft verschachtelten '[quote]'-Tags, da hier dann der ohnehin schon fehlerhaft zitierte Text noch mehr "verstümmelt" wird. Dabei kann es dann schnell mal vorkommen, dass bei unachtsamen Usern das Zitat falsch gedeutet wird.

Wie umgeht man dieses Problem also nun? Durch das 'U' (Dieses hier: '.../Us') ist gewährleistet, dass dieser Regex Ungreedy arbeitet, also das nächste vorkommende '
' nutzen will und nicht, wie es standard wäre, das letzte, das er findet. Aber: Er soll auch das zugehörige 'b'-BB-Code-Tag verwenden und nicht das erste, was in dem genannten Beispiel zur entsprechend fehlerhaften ausgabe führte. Wenn wir also folgendes Ergebnis haben wollen:

Code:
Dies ist ein Test mit verschachtelten BB-Codes. 
PHP-Code:
<?php
/* ... */
$text preg_replace ('/\[(b)(\:[\d]+)\](.*)\[\/\1\2\]/Us''[b]\\3<b>

Müssen wir den Text vorher parsen und hinterher den BB-Code erst ersetzen. Es ist mit Regex möglich Backreferences zu setzen, die es uns erlauben, die zugehörigen BB-Codes zu ermitteln:

</b>'
$text);
/* ... */
?>
In diesem Beispiel habe ich unter anderem auch das zweite 'b' durch Backreferences ersetzt. Das '\1' setzt in das '[/]' also das 'b' ein -> '
' und durch das '\2' bekommen wir in den Tag noch die zugehörige Nummer '[/b:123]'.

Haben wir nun also vorliegenden Code:

Code:
[b:1]Dies ist ein Test [b:2]mit verschachtelten BB-Codes[/b:2].
wird durch unseren Regex das gewünschte Ergebnis erziehen:

Code:
Dies ist ein Test mit verschachtelten BB-Codes. 


Aber: Wie bekommen wir jetzt möglichst unproblematisch die Zahlen eingefügt? Eigentlich ganz einfach. Wir lesen erstmal alles an BB-Codes aus, was vorhanden ist:

PHP-Code:
<?php
/* ... */
$bbcode = array ();

if (
preg_match_all ('/(?:\[(\/)?(b)\])/s'$text$vars) > 0)
{
  
/* Folgt gleich weiter unten im Tutorial (FOR-Schleife) */
}
/* ... */
?>
Das Array $bbcode benötigen wir gleich für die Abarbeiung von BB-Codes.
Mit unserem Beispiel erhalten wir nun 3 Ergebnisse des Regex': 'b'-BB-Code-Tag, 'b'-BB-Code-Tag und '/b'-BB-Code-Tag. Nun muss nurnoch das entsprechende Ergebnis ausgewertet werden:

PHP-Code:
<?php
/* ... */
  
for ($i 0;
  
$i count ($vars[0]);
  
$i++)
  {
    if (empty (
$vars[1][$i]) === TRUE)
    {
      if (isset (
$bbcode[$vars[2][$i]]) === FALSE)
     {
        
$bbcode[$vars[2][$i]] = 0;
      }
      
$bbcode[$vars[2][$i]]++;
    }

    
$text preg_replace ('/'.preg_quote ($vars[0][$i], '/').'/s''['.$vars[1][$i].$vars[2][$i].':'.$bbcode[$vars[2][$i]].$vars[3][$i].']'$text1);

    if (
$vars[1][$i] == '/'
    
&& $bbcode[$vars[2][$i]] > 0)
    {
      
$bbcode[$vars[2][$i]]--;
    }
  }

  
$text preg_replace ('/(?:\[(\/)?(b)\:0\])/s''[\\1\\2]'$text);
/* ... */
?>
Wie man hier unschwer erkennen kann, wird in dem Array der entsprechende BB-Code hoch bzw. runtergezählt, jenachdem, ob ein BB-Code-Tag geöffnet (erhöht) oder geschlossen (verringert) wird. Wenn bei 0 angekommen wird, wird nicht weiter runter gezählt. Alle BB-Code-Tags, die ein ':0' besitzen sind somit automatisch überflüssig und werden durch das letzte 'preg_replace' wieder in ihre Ausgangsposition versetzt (ohne ':0'). Es ist jedoch notwendig, vorher das ':0' einzufügen, da die erste 'preg_replace'-Funktion das erste Vorkommen des Suchstrings ersetzt und es sonst zu fehlern führt, wenn wir z.B. folgenden Text haben:

Code:
[b:1]Dies ist ein Test [/b:1]mit fehlerhaften BB-Codes[/b:1] [b:1]die zur Falschausgabe führen
Code:
.
Sowas wollen wir natürlich auch vermeiden, deswegen sieht nach der FOR-Schleife unser Text auch so aus:

Code:
[b:1]Dies ist ein Test [/b:1]mit fehlerhaften BB-Codes[/b:0] [b:1]die zur Falschausgabe führen[/b:1].
und nach der Anwendung des letzten 'preg_replace' so:

Code:
[b:1]Dies ist ein Test [/b:1]mit fehlerhaften BB-Codes
[/b]
Code:
 [b:1]die zur Falschausgabe führen[/b:1].
Wir haben also unser Ziel erreicht und mittels:

PHP-Code:
<?php
/* ... */
unset ($temp);
while (
$temp != $text)
{
  
$temp $text;
  
$text preg_replace ('/\[(b)(\:[\d]+)\](.*?)\[\/\1\2\]/s''[b]\\3[/b]'$text);
}
/* ... */
?>
erhalten wir das gewünschte Ergebnis.

Ich hoffe dass mancher dieses Tutorial als sinnvoll erachtet, der sich an der selben Problematik gestört fühlt, wie ich

MfG
MNG
MrNiceGuy ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 14.08.2005, 00:08  
Erfahrener Benutzer
 
Registriert seit: 21.05.2008
Beiträge: 387
MrNiceGuy befindet sich auf einem aufstrebenden Ast
Standard

Eine Kleinigkeit ist mir heute noch aufgefallen: Bei fehlerhaftem BB-Code kann es auch passieren, dass z.B. 'b'-BB-Code-Tags am Anfang übrig bleiben. Diese haben dann als Numerischen Indikator nicht die 0. Somit wird auch deren Numerierung nicht entfernt.

Dies kann man umgehen, indem man anstatt:

PHP-Code:
<?php
/* ... */ 
  
$text preg_replace ('/(?:\[(\/)?(b)\:0\])/s''[\\1\\2]'$text); 
/* ... */ 
?>
VOR der Ersetzung des BB-Codes ein:

PHP-Code:
<?php
/* ... */ 
  
$text preg_replace ('/(?:\[(\/)?(b)\:[\d]+\])/s''[\\1\\2]'$text); 
/* ... */ 
?>
NACH der Ersetzung macht.
MrNiceGuy ist offline   Mit Zitat antworten
Alt 14.08.2005, 16:33  
Erfahrener Benutzer
 
Registriert seit: 27.10.2004
Beiträge: 1.093
PHP-Kenntnisse:
Fortgeschritten
Chr!s
Standard

Nette Methode die diese Problematik anspricht. Ich habe das Problem in meinem Code mehr umgangen als gelöst (falls es jemanden interessiert):
PHP-Code:
<?php
        
var $bbcodes = array('#\[b\]#ismU' =>
                                  
'<span style="font-weight:bold">',

                            
'#\[/b\]#ismU'=>
                                  
'</span>',

                            
'#\[i\]#ismU' =>
                                  
'<span style="font-style:italic">',

                            
'#\[/i\]#ismU'=>
                                  
'</span>',

                            
'#\[u\]#ismU' =>
                                   
'<span style="text-decoration:underline">',

                            
'#\[/u\]#ismU' =>
                                  
'</span>',
// ...
?>
Indem ich die Replacements hier einzeln und nicht als komplettpattern (etwa #\[b\](.*?)\[/b\]#imsU) angebe. Das replacement wird dann ganz einfach mit folgendem Code ausgeführt:
PHP-Code:
<?php
$text 
preg_replace(array_keys($this -> bbcodes), array_values($this -> bbcodes), $text);
?>
Ich hoffe ich konnte jemandem mit meinem Beitrag helfen
Chr!s ist offline   Mit Zitat antworten
Alt 14.08.2005, 23:30  
Benutzer
 
Registriert seit: 22.04.2005
Beiträge: 70
CrackPod
Standard

@chr!s:

kann man deinen code einfach so übernehmen, denn ich versteh das oben atm nicht so ganz....

kann auch ander uhrzeit liegen in verbindung mit der dauer, die ich schon wach bin...
CrackPod ist offline   Mit Zitat antworten
Alt 14.08.2005, 23:32  
Erfahrener Benutzer
 
Registriert seit: 27.10.2004
Beiträge: 1.093
PHP-Kenntnisse:
Fortgeschritten
Chr!s
Standard

Naja, mein Code ist jetzt direkt aus meiner alten Klasse heraus kopiert.. Im Grunde aber ja, bis auf das var und die $this -> ..
Nur ist das was ich geschrieben habe die Rohversion, htmlentities() und die ganzen Bearbeitungen, die mit dem Text gemacht werden müssen stehen in meinem Post von oben nicht ..
Chr!s ist offline   Mit Zitat antworten
Alt 14.08.2005, 23:35  
Erfahrener Benutzer
 
Registriert seit: 21.05.2008
Beiträge: 387
MrNiceGuy befindet sich auf einem aufstrebenden Ast
Standard

@Chr!s: Damit wird aber alles übersetzt und das ist ja nicht Sinn und Zweck der Übung, denn dann erhälst du fehlerhaften bzw. unvollständigen HTML-Code.

Zu dem Problem, was du heute gepostet hattest (und wieder entfernt hast aus welchem Grund auch immer), habe ich die While-Schleife in meinem ersten Post reineditiert. Ich hatte vergessen, dass BB-COdes innerhalb vorhandener BB-Codes ignoriert werden, da die nächste Suche nach dem vorangegangenen Suchergebnis weitergeht.
MrNiceGuy ist offline   Mit Zitat antworten
Alt 08.09.2006, 22:58  
Erfahrener Benutzer
 
Registriert seit: 03.01.2006
Beiträge: 253
CC84
Standard

DIe Idee an sich sieht gut aus, aber wie siehts mit der Performance aus, bzw. wo macht ihr das? Schreibt ihr die vorbereiteten Tags in die DB oder bereiteter ihr alle Texte jedesmal aufs neue so vor, wenn ein User sie ausliest?
CC84 ist offline   Mit Zitat antworten
Alt 09.09.2006, 10:52  
Erfahrener Benutzer
 
Registriert seit: 01.02.2004
Beiträge: 550
cytrobic
Standard

man kann doch prüfen ob nach einem < b > ein < /b > oder wieder ein [ b ] kommt und dementsprechend dann entwerder das zweite [ b ] löschen oder durch [ /b ][ b ] ersetzen und mitzählen und am ende des post evtl. vergessene [ /b ] hinzufügen.

so ? [/b]
__________________
keine
cytrobic ist offline   Mit Zitat antworten
Alt 10.09.2006, 14:46  
Erfahrener Benutzer
 
Benutzerbild von DER_Brain
 
Registriert seit: 18.04.2005
Beiträge: 1.541
PHP-Kenntnisse:
Fortgeschritten
DER_Brain ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Wenn du eine Nachricht schreibst siehst du über dir so Buttons ("B","i","u",...)

Wenn du auf einen klickst dann wird eine eckige klammer + das Symbol eingefügt:

[ b ] (ohne Leerzeichen..)

Der Text, der zwischen den beiden steht wird FETT, Kursiv, Unterstrichen, ... angezeigt!
bei nochmaligem Klick wird dieses eingefügt:
[ /b ] (ohne Leerzeichen..)


mfg
Andi
DER_Brain ist offline   Mit Zitat antworten
Alt 10.09.2006, 21:13  
Erfahrener Benutzer
 
Registriert seit: 03.01.2006
Beiträge: 253
CC84
Standard

Zitat:
Zitat von DER_Brain
Wenn du eine Nachricht schreibst siehst du über dir so Buttons ("B","i","u",...)

Wenn du auf einen klickst dann wird eine eckige klammer + das Symbol eingefügt:

[ b ] (ohne Leerzeichen..)

Der Text, der zwischen den beiden steht wird FETT, Kursiv, Unterstrichen, ... angezeigt!
bei nochmaligem Klick wird dieses eingefügt:
[ /b ] (ohne Leerzeichen..)


mfg
Andi
Darf ich mal fragen worauf ihr alle antwortet? Das hat alles mit meienr Frage wenig zu tun.

Gruß

CC
CC84 ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
regex verschachtelt, bbcode verschachteln, bbcode verschachtelt, verschachtelter bbcode, alle bbcode, regex verschachtelung, bbcodes verschachteln, verschachtelte bbcodes, php verschachtelung, http://www.php.de/tutorials/29070-bb-code-loesungsansatz-bei-verschachtelung.html, regex verschachteltes html, regexp verschachteln, bb code verschachteln, php verschachtelte bbcodes, preg_replace bbcode tutorial, bbcode verschachtelt php, preg_replace verschachtelt, bbcode verschachtelung, php bbcode verschachteln, php tag verschachteln

Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum

Creative Commons License
Dieser Inhalt ist unter einer Creative Commons-Lizenz lizenziert.