2013-08-15 1 views
1

Мне нужно динамически добавлять активный класс к короткому коду в wordpress на основе активного номера, установленного в его родительском коротком коде.Как заменить N-й экземпляр строки в PHP?

Родитель выглядит следующим образом:

$active = 3; 
$output .= "\n\t\t".wpb_js_remove_wpautop($content); 

переменные $ содержания технически может состоять из ничего между тегами Шорткодов, но в частности, должен включать в себя несколько дочерних шорткоды (это вкладка шорткод поэтому родитель закладка и дети - вкладка).

Что мне нужно сделать, это разобрать $content и заменить NTH ($active переменные) экземпляр [vc_tab с [vc_tab active="true"

Я понимаю, что есть лучшие способы для разработки шорткода, чтобы компенсировать это, но я ограничен в чем я может быть, потому что я модифицирую Visual Composer для использования вкладок Bootstrap вместо вкладок jQuery и Bootstrap, которые должны иметь активный класс как для <li>, так и для элементов <div class="tab-pane">, но я не хочу, чтобы пользователям приходилось добавлять активный номер в родительский код и активный true/false для ребенка, так как это будет запутывать.

До сих пор я не могу найти замену первого вхождения или всех вхождений, а не N-го.

Временно я использую jQuery, чтобы сделать соответствующий <div> активным, но это приводит к нежелательной FOUC, когда нет видимой области видимости при загрузке, а затем один всплывает на место при запуске jQuery.

$('.tabs-wrap').each(function(){ 
    var activeTab = $(this).find('.tabbed li.active a').attr('href'); 
    $(this).find(activeTab).addClass('active'); 
}); 

ответ

3

Это интересная проблема, и я подумал , если вам действительно нужно для регулярного выражения.

Мое заключение заключается в том, что я не верю, что вы это делаете. Все, что вам нужно сделать, это найти нахождение Nth$needle и заменить его на замену. Это может быть достигнуто посредством простой струйной манипуляции следующим образом:

  1. Определить некоторые переменные. Ваша строка ввода, ваш индекс $active, $needle, который мы ищем, и $replace, что мы заменим матч Nth.

    $string = "[vc_tab [vc_tab [vc_tab [vc_tab [vc_tab [vc_tab"; 
    $active = 3; 
    $needle = "[vc_tab"; 
    $replace = '[vc_tab active="true"'; 
    
  2. Теперь мы должны убедиться, что есть достаточно $needle s в $string, в противном случае мы не можем сделать эту замену.

    if(substr_count($string, $needle) < $active) { 
        throw new Exception("There aren't enough needles in the string to do this replacement"); 
    } 
    
  3. Теперь мы знаем, что можем сделать замену. Так давайте найдем $index в строке, где Nth возникновение $needle заканчивается:

    $count = 0; $index = 0; 
    while($count++ < $active) { 
        $index = strpos($string, $needle, $index) + strlen($needle); 
    } 
    
  4. Теперь $index указывает здесь в строке:

    [vc_tab [vc_tab [vc_tab [vc_tab [vc_tab [vc_tab 
            ^
             Here 
    

    Теперь мы можем сделать несколько простых substr() «ю.ш. для формирования окончательной строки:

    $result = substr($string, 0, $index - strlen($needle)) . $replace . substr($string, $index); 
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^ 
          Before the Nth match          After the Nth match 
    

    Итак, в итоге мы конкатенируем:

    • [vc_tab [vc_tab
    • [vc_tab active="true"
    • [vc_tab [vc_tab [vc_tab

Это приводит в наших final output:

[vc_tab [vc_tab [vc_tab active="true" [vc_tab [vc_tab [vc_tab 

Попробуйте в the demo!

+0

Спасибо, это отлично работает, за исключением того, что вместо исключения исключения при проверке ошибок I просто установите '$ active = 1' (возврат к значению по умолчанию) – tsdexter

2

Я не знаком с инструментами, вы упоминаете, так что я не могу сказать, если есть лучший способ для достижения конечной цели, но вы можете заменить Nth появления чего-то с помощью preg_replace_callback:

$active = 3;  // target occurrence 
$occurrence = 0; // counter 
$output = preg_replace_callback(
    '/\[vc_tab/', 
    function ($matches) use(&$occurrence, $active) { 
     return ++$occurrence != $active 
      ? $matches[0] 
      : '[vc_tab active="true"'; 
    }, 
    $output, 
    $active 
); 

See it in action.

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

Обратите внимание, что я прошел $active как максимальное количество замещений для замены, чтобы получить бесплатное увеличение производительности; это приведет к тому, что preg_replace_callback остановится после того, как $active замещения были заменены (мы знаем, что все вхождения после этого будут заменены сами собой, поэтому нет смысла продолжать).

+0

спасибо за помощь. preg_replace_callback выглядит как полезная функция, чтобы иметь в виду, но этот код не работал с реальным миром $ output, а не отлаживал его, я использовал метод манипуляции строкой, ниже которого может быть более эффективным, чем регулярное выражение? – tsdexter

+0

@tsdexter: Я не уверен, что манипуляции на низком уровне, вероятно, нужно будет оптимизировать, но я бы не рискнул угадать (измерить, если это важно). Не уверен, почему это не сработает для вас, так как код читается довольно чистым. – Jon

+0

хорошо теперь мне любопытно, поэтому мне придется разобраться. – tsdexter

Смежные вопросы