Jump to content
  • 0

BBCode - преобразование тегов


Мнфсруыдфм
 Share

Question

пишу форум и возникла тут такая альтернатива:

хочу ввести в форуме поддержку BBCode т.е. пользователь сможет используя теги вроде

|quote||/quote| |code| |/code| |img| |img| (скобки квадратные, заменил тут на прямые что-бы этот форум их не преобразовал в теги) форматировать сообщения. Собственно саму функцию уже реализовал. В базе храниться таблица с кодами в виде

{quote=; <span class="quote">$N</span><blockquote class="quote">; </blockquote>}

по этим записям функция меняет теги в BBCode на теги HTML все нормально работает, но вот не пойму как сделать редактирование уже введенных сообщений. Пользователю то надо подсовывать текст не с тегами HTML а с тегами BBCode.

Если хранить сообщения преобразованные в HTML, то обратное преобразование в BBCode это довольно заморочное дело (надо учесть то что закрывающие теги, например могут принадлежать разным тегам BBCode и т.д. в общем кусок работы.

Если же хранить сообщения в базе не преобразованные а преобразовывать их непосредственно перед выводом, то повысится нагрузка на сервер - в принципе функция шустрая, но при большом количестве пользователей не знаю как себя поведет, могут появиться тормоза.

Можно, конечно еще хранить два вида сообщений, в html и в BBCode, но как-то это негламурненько :)

Может быть я изобретаю велосипед и есть какой-то другой способ?

Link to comment
Share on other sites

Recommended Posts

  • 0

В общем, можно вопрос сформулировать и так.. если все обычно хранят сообщения не преобразованные в html, в BBCode а преобразовывают их на лету при формировании страницы, насколько это сильно тормозит сервер? А то может быть я застрял на ерунде и крохоборствую тут вместо того что-бы делом заняться :)

Link to comment
Share on other sites

  • 0
Если хранить сообщения преобразованные в HTML, то обратное преобразование в BBCode это довольно заморочное дело (надо учесть то что закрывающие теги, например могут принадлежать разным тегам BBCode и т.д. в общем кусок работы.

Помоему проблем нет, какая разница тот или другой ?

Если же хранить сообщения в базе не преобразованные а преобразовывать их непосредственно перед выводом, то повысится нагрузка на сервер - в принципе функция шустрая, но при большом количестве пользователей не знаю как себя поведет, могут появиться тормоза.

По опыту сервер это не нагружает, во всяком случае не больше чем SQL запросы :)

Link to comment
Share on other sites

  • 0
Можно, конечно еще хранить два вида сообщений, в html и в BBCode, но как-то это негламурненько

Это нормально/гламурно. Риальные пацаны так и поступают. Сами храним 2 формата (wiki/xhtml).

в общем, как я понял, пацаны если что поймут :P:)

значит буду так и делать, вариант с преобразованием html в BBCode мне что-то сильно не нравиться, да и перекодировка на лету тоже, надеюсь что форум будет сильно посещаемым, некчему лишняя нагрузка, да и место на винте теперь не такое дорогое как раньше.

спасибо за уничтожение моих колебаний, а то я уже заколебался сам и заколебал окружающих своим мрачным видом :P

Link to comment
Share on other sites

  • 0
Помоему проблем нет, какая разница тот или другой ?

ну, например:

|u|бла-бла|/u| преобразуется в бла-бла

и если перегонять этот код html назад в BBCode, то нужно как-то определить что принадлежить иенно тегу |u| а не |s| например. Конечно ничего невозможного в этом нет, но все-же довольно заморочное дело как мне кажется. Проще все-же хранить в двух видах.

Link to comment
Share on other sites

  • 0
Можно, конечно еще хранить два вида сообщений, в html и в BBCode, но как-то это негламурненько

Это нормально/гламурно. Риальные пацаны так и поступают. Сами храним 2 формата (wiki/xhtml).

Ну вообще-то я бы так делать не стал.

Конвертировать налету - это гораздо рациональней. Возможно это конечно занимает лишние микросекунды в производительности скрипта, но на практике этого никто не ощущает. Ерунда это все. Время на выполнение комманд str_replace совсем незначительное, его даже измерить с точностью проблематично.

Зато подумайте о том, что сейчас вы просто пишете свой форум. В данный момент он пустой, а что будет в тот момент, когда на вашем сайте будет более 10000 сообщений.

Например БД с таким форумом может весить 7-10mb (а может и больше). Если вы будете хранить в БД некие фрагменты разных кодирований HTML, BB Code, XML, wiki и.т.д то размер вашей БД увеличится не на пару килобайт, а неизвестно во сколько раз.

Кроме того: - Если у вас присутствует только BB Code и HTML, то в тот момент когда вы захотите добавить к своей системе еще какой либо стандарт, то у вас просто не будет записей старых сообщений с BB Code для этого стандарта и вам придется их делать вручную. Иными словами теряется ГИБКОСТЬ системы.

ЗЫ просто не встречал я таких новществ ни в одной CMS системе. Можно конечно гордиться насколько у нас все круто, но по моему (ИМХО) это головная боль ни о чем.

Link to comment
Share on other sites

  • 0
|u|бла-бла|/u| преобразуется в бла-бла

и если перегонять этот код html назад в BBCode, то нужно как-то определить что принадлежить иенно тегу |u| а не |s| например. Конечно ничего невозможного в этом нет, но все-же довольно заморочное дело как мне кажется. Проще все-же хранить в двух видах.

А Зачем span ? когда для подч?ркивания есть ?

Link to comment
Share on other sites

  • 0
Ну вообще-то я бы так делать не стал.

Конвертировать налету - это гораздо рациональней. Возможно это конечно занимает лишние микросекунды в производительности скрипта, но на практике этого никто не ощущает. Ерунда это все. Время на выполнение комманд str_replace совсем незначительное, его даже измерить с точностью проблематично.

...

Если у вас присутствует только BB Code и HTML, то в тот момент когда вы захотите добавить к своей системе еще какой либо стандарт, то у вас просто не будет записей старых сообщений с BB Code для этого стандарта и вам придется их делать вручную. Иными словами теряется ГИБКОСТЬ системы.

...

Мммда, в принципе логично.. Меня то как раз вопрос производительности больше всего и беспокоил, понятно что сейчас все летает - форум пустой, но если действительно не стоит этим грузиться то сделаю все-же хранение в коде и правку налету.

Link to comment
Share on other sites

  • 0
но на практике этого никто не ощущает. Ерунда это все. Время на выполнение комманд str_replace совсем незначительное, его даже измерить с точностью проблематично.

Еще как ощущают. Тем более что там предполагается не str_replace, а нехилый такой regExp. И нагрузка будет огого какая.

Конечно зависит от посещаемости и производительности железки.

В любом случае пусть лучше трудится бинарный MySQL чем интерпретатор PHP

Например БД с таким форумом может весить 7-10mb (а может и больше)

И что? БД можеть весит гораздо гораздо больше.

Если вы будете хранить в БД некие фрагменты разных кодирований HTML, BB Code, XML, wiki и.т.д то размер вашей БД увеличится не на пару килобайт, а неизвестно во сколько раз.

Вот это правда. Но более 2х форматов (html + второй) хранить никогда не понадобится.

Кроме того: - Если у вас присутствует только BB Code и HTML, то в тот момент когда вы захотите добавить к своей системе еще какой либо стандарт, то у вас просто не будет записей старых сообщений с BB Code для этого стандарта и вам придется их делать вручную. Иными словами теряется ГИБКОСТЬ системы.

Написать робота - 2 часа делов.

ЗЫ просто не встречал я таких новществ ни в одной CMS системе.

Теперь понятно.

Link to comment
Share on other sites

  • 0
Тем более что там предполагается не str_replace, а нехилый такой regExp. И нагрузка будет огого какая.

Конечно зависит от посещаемости и производительности железки.

В любом случае пусть лучше трудится бинарный MySQL чем интерпретатор PHP

да, функция довольно нехилая получилась

$this->patTag="~([[^[]*])~";
$this->patOpenTag="~[s*([^/][^s]*?)s*(?:="?(.+?)"?)?s*]~";
$this->patCloseTag="~[s*/s*([^s]+)s*]~";

function GetHTTPFromBB($N,$i,$j){
$ot=$this->HTMLtag;
$ot=str_replace('$N',$N,$ot);
$this->tegArr[$i]=$ot;
$this->tegArr[$j]=$this->HTMLTagClose;
}

function IsOpenTag($s,&$T,&$N){
$r= preg_match($this->patOpenTag,$s,$g);
if (count($g)>1){
$T=$g[1];
$N="";
if (count($g)==3)
$N=$g[2];
}
return $r;
}

function IsCloseTag($s,&$T){
$r= preg_match($this->patCloseTag,$s,$g);
if (count($g)==2){
$T=$g[1];
}
return $r;
}

function CheckHierarchy(){
$stack[0]=Array(0,"","");

$this->errors="";

for ($i=0; $i<count($this->tegArr); $i++) {
if($this->IsOpenTag($this->tegArr[$i],$T,$N)){
//Если тег
$stack[count($stack)]=Array($i,$T,$N);
}
elseif($this->IsCloseTag($this->tegArr[$i],$T)){

if (count($stack)==1){
$this->errors.=
"Закрывающему тегу [/$T] не найден соответствующий открывающий
";
continue;
}

if ($stack[count($stack)-1][1]==$T){

$N=$stack[count($stack)-1][2];

if (!$this->FindTag($T,$N)||(!$this->Enabled)){
//такого тега нет!
$this->errors.=
"Тег <strong>[$T]</strong> не поддерживается".
" форумом или отключен администрацией
";

unset($stack[count($stack)-1]);
continue;
}
//все ОК
$this->GetHTTPFromBB($N,
$stack[count($stack)-1][0],
$i);

unset($stack[count($stack)-1]);
}
else{
$this->errors.="Неправильная последовательность тегов! ";
$this->errors.="([".$stack[count($stack)-1][1]."]—>[/$T])
";
return false;
}

}
}

if (count($stack)==1) return true;

$this->errors.="Незакрытые теги: ";
foreach($stack as $key=>$value)
if($key)
$this->errors=$this->errors."[".$value[1]."] ";
$this->errors=$this->errors." ";

return false;
}

//анализирует теги и формируюе выходную строку
//в случае нормального завершения выдает отформатированный текст
function GetString(){
$Count=count($this->tegArr);
if (!$Count) return "";
$this->errors="";
$this->valid=$this->CheckHierarchy();
//сформируем результат
$s="";
foreach($this->tegArr as $value)$s.=$value;
return $s;
}

Link to comment
Share on other sites

  • 0

Попробовал оба варианта, пока что на тестовом форуме (около 200 кБ текста) вроде не тупит, наверное сделаю так, пока пусть все хранится в BBCode, если жизнь покажет что будут тормоза перегнать его в HTML это как два байта переслать, дело максимум на полчас неспешной работы.

Link to comment
Share on other sites

  • 0

Я бы посоветовал вам такое решение. Выражение, например

|u| подчеркнутый текст |/u|

хранить в базе в виде

подчеркнутый текст class="underlined">

В общем, в закрывающем теге прописать - к чему он относится. Варианты:

underlined>

u>

Я проверял - работает.

Плюсы:

не нужно хранить два формата

не нужно использовать regexp - можно обойтись и str_replace

Минусы:

противоречие спецификации (я думаю)..

Link to comment
Share on other sites

  • 0

мысль хорошая, но

Минусы:

противоречие спецификации (я думаю)..

я тоже думаю что противоречит (может и ошибаюсь, я в этом деле еще чайник :)).

Дело в том что это дипломная работа (но форум будет реально использоваться, пишу не "для полки", его планируют разместить на новом сайте университета), поэтому правильность кода довольна важна, проще вообще отказаться от BBCoda :P. Вообще, надеюсь, что странички будут валидными, когда подработаю напильником :P

Link to comment
Share on other sites

  • 0

получается можно обрабатывать BBCod на входе, и сохранять его в базе в виде "...[Название_BB_тега] > а потом, при выводе менять эти неправильные теги, просто удаляя все что в квадратных скобках с самими скобками, это делаться будет быстро, и перед редактированием получить из такого "полуBBCode" реальный код будет довольно легко. Как говорят в американских фильмах, это должно сработать :)

Link to comment
Share on other sites

  • 0
получается можно обрабатывать BBCod на входе, и сохранять его в базе в виде "...[Название_BB_тега] > а потом, при выводе менять эти неправильные теги, просто удаляя все что в квадратных скобках с самими скобками, это делаться будет быстро, и перед редактированием получить из такого "полуBBCode" реальный код будет довольно легко. Как говорят в американских фильмах, это должно сработать :)

А смысл ? проще хранить BBCode и конвертить в валидный хтмл на выходе

Link to comment
Share on other sites

  • 0

вот еще придумал..

А что если сохранять сообщение в отдельной табличке. Т.е. при получении постинга парсим BBCode и записываем его вместе с текстом и HTML в такую таблицу:

IDпоста | Текст
——————————————-
ID0 | ... собственно текст
ID1 | [BBTag]<HTMLTag> теги
ID0 | ... собственно текст
ID0 | ... собственно текст
ID0 | ... собственно текст
ID1 | [BBTag]<HTMLTag> теги

тогда получится что и избыточного хранения информации нет и любой код можно налету формировать, достаточно выбросить из строки ненужные теги и склеить строки таблицы в одну

Link to comment
Share on other sites

  • 0

Хе, ну вот вам еще один вариант.

В отдельном поле храните последовательность BB-тегов для каждого сообщения форума.

Сами комменты франите в HTML, как положено, с обычными .

Далее, когда будете HTML преобразовывать назад в BB-код, то заменяете каждый HTML-тег соответсвующим BB-тегом из сохраненной последовательности.

Пример:

Это жирный шрифт, а это подчеркнутый

В BB-тегах:

Это |b|жирный шрифт|/b|, а это |u|подчеркнутый|/u|

В базе в HTML-тегах:

Это жирный шрифт, а это подчеркнутый

Поле с последовательностью BB-тегов:

|b|,|/b|,|u|,|/u|

Подобный метод займет гораздо меньше места в базе, чем хранение сообщений в двух экземплярах.

Чтобы извлечь BB-теги из сообщения во время его отправки, достаточно один раз пройтись по строке - сложность алгоритма - линейная.

При преобразовании из HTML в BB, BB-теги можно получить, допустим, так:

$bbtags = explode(',', $bbsequence);

Подумайте над этим..

Link to comment
Share on other sites

  • 0

Ну в принципе согласен с PcMan.

Если ему потребовалось хранить два стандарта в БД, значит на то есть причины, надеюсь они себя оправдывают.

Высказал я свое мнение руководствуясь теорией вероятности, но не принимайте это за аксиому. Делайте как вам удобно.

Просто пока с такими проблемами я наверное не сталкивался (с загрузкой сервера из-за BB-Code)...

А функция парсинга BB-Code не такая уж и сложная и замороченная....

Link to comment
Share on other sites

  • 0
Чтобы извлечь BB-теги из сообщения во время его отправки, достаточно один раз пройтись по строке - сложность алгоритма - линейная.

При преобразовании из HTML в BB, BB-теги можно получить, допустим, так:

$bbtags = explode(',', $bbsequence);

Подумайте над этим..

Хорошая идея!

У меня еще другая появилась :) (чем и хороши форумы - сформулировал вопрос, уже на 90% нашел решение :P)

Надо просто использовать две функции преобразования BBCode (ну, или одну, работающую в двух режимах, это не важно)

Первая функция "продвинутая и интеллектуальная", она контролирует правильность кода, соответствие закрытых и открытых тегов, вложенность тегов и т.п. Если что-то не так то скрипт не сохраняет сообщение в базе, если все ОК то сообщение записывается в базу как есть, т.е. в BBCode.

Вторая функция "тупая", но быстрая, она просто загружает из базы таблицу соответствий BBCoda и html, запихивает их в массивы $search и $replace и дальше

$s=str_replace ($search, $replace, $s);

Код там уже проверенный заморачиваться проверками не надо, зато замена будет производиться с максимальной скоростью.

Link to comment
Share on other sites

  • 0

Мнфсруыдфм

Делайте, как вам удобнее.

Советую посмтреть исходники phpBB, IPB, vBulletin - как это реалзиовано там. Над ними ведь тоже не дураки работают, и если они сделали так или иначе, то на это, наверное, нашилсь свои причины... :)

Link to comment
Share on other sites

  • 0
Мнфсруыдфм Советую посмтреть исходники phpBB, IPB, vBulletin - как это реалзиовано там. Над ними ведь тоже не дураки работают, и если они сделали так или иначе, то на это, наверное, нашилсь свои причины... :)

А чего там смотреть?

Во всех системах CMS как раз так и реализованы функции парсинга BB Кодов. Замена BB Кодов выполняется налету, при выводе HTML странички. В БД хранится только одна запись сообщений, именно такая какая есть (с BB Кодами).

И делается это как правило при помощи какой-нить функции парсинга ВВ Кодов прямо в функции print или echo

Пример

Link to comment
Share on other sites

  • 0

спасибо за пример, поначалу думал так и сделать, только регулярные выражения хранить в базе (а не внутри кода), что-бы без правки кода можно было добавить или убрать теги. Но захотелось еще сделать разбор, с выводом ошибок (закрытые, незакрытые теги и т.п.) только уже сейчас сообразил что можно было после прогона регулярными выражениями поискать оставшиеся теги и их уже проанализировать, правда у моего варианта есть и преимущества - админ форума может добавлять теги вообще ничего не понимая в регулярных выражениях, достаточно знать немного HTML :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy