【问题标题】:Place content in between paragraphs without images在没有图像的段落之间放置内容
【发布时间】:2014-02-28 09:53:02
【问题描述】:

我正在使用以下代码在我的内容中放置一些广告代码。

<?php
$content = apply_filters('the_content', $post->post_content);
$content = explode (' ', $content);
$halfway_mark = ceil(count($content) / 2);
$first_half_content = implode(' ', array_slice($content, 0, $halfway_mark));
$second_half_content = implode(' ', array_slice($content, $halfway_mark));
echo $first_half_content.'...';
echo ' YOUR ADS CODE';
echo $second_half_content;
?>

我如何修改它,使包含广告代码的 2 个段落(顶部和底部)不应该是有图片的段落。如果顶部或底部的段落有图片,然后尝试下 2 个段落。

示例:右侧的正确实现。

【问题讨论】:

  • 你的问题是$item里面有图片吗?不确定我是否关注。
  • 从您的项目中过滤&lt;img&gt;标签?我不确定你到底想要什么。
  • @Olavxxx 我已经更新了问题
  • @user1781026 更新了问题
  • 您是否将广告作为图片放在常规帖子中,然后希望它们出现在您内容的“中间”?如果是这样,我认为这最好通过 CSS 完成?

标签: php html


【解决方案1】:

preg_replace 版本

此代码逐步遍历每个段落,忽略包含图像标签的段落。 $pcount 变量会随着每个没有图像的段落而增加,但是如果遇到图像,$pcount 会重置为零。一旦$pcount 达到它会达到两个的点,广告标记就会插入到该段落之前。这应该在两个安全段落之间留下广告标记。然后广告标记变量被无效,因此只插入一个广告。

以下代码仅用于设置,可以修改以不同地拆分内容,您还可以修改使用的正则表达式 - 以防您使用双 BR 或其他东西来分隔段落。

/// set our advert content
$advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n";
/// calculate mid point
$mpoint = floor(strlen($content) / 2);
/// modify back to the start of a paragraph
$mpoint = strripos($content, '<p', -$mpoint);
/// split html so we only work on second half
$first  = substr($content, 0, $mpoint);
$second = substr($content, $mpoint);
$pcount = 0;
$regexp = '/<p>.+?<\/p>/si';

其余的是运行替换的大部分代码。这可以修改为插入多个广告,或支持更多涉及的图像检查。

$content = $first . preg_replace_callback($regexp, function($matches){
  global $pcount, $advert;
  if ( !$advert ) {
    $return = $matches[0];
  }
  else if ( stripos($matches[0], '<img ') !== FALSE ) {
    $return = $matches[0];
    $pcount = 0;
  }
  else if ( $pcount === 1 ) {
    $return = $advert . $matches[0];
    $advert = '';
  }
  else {
    $return = $matches[0];
    $pcount++;
  }
  return $return;
}, $second);

执行此代码后,$content 变量将包含增强的 HTML。


5.3 之前的 PHP 版本

由于您选择的测试区域不支持PHP 5.3,因此不支持匿名函数,您需要使用稍微修改且不那么简洁的版本;而是使用命名函数。

另外,为了支持在下半场可能实际上没有为广告留出空间的内容,我修改了$mpoint,以便从最后计算为 80%。这将产生在$second 部分中包含更多内容的效果——但也意味着您的广告通常会在标记中放置得更高。这段代码没有实现任何回退,因为您的问题没有提到在失败时应该发生什么。

$advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n";
$mpoint = floor(strlen($content) * 0.8);
$mpoint = strripos($content, '<p', -$mpoint);
$first  = substr($content, 0, $mpoint);
$second = substr($content, $mpoint);
$pcount = 0;
$regexp = '/<p>.+?<\/p>/si';

function replacement_callback($matches){
  global $pcount, $advert;
  if ( !$advert ) {
    $return = $matches[0];
  }
  else if ( stripos($matches[0], '<img ') !== FALSE ) {
    $return = $matches[0];
    $pcount = 0;
  }
  else if ( $pcount === 1 ) {
    $return = $advert . $matches[0];
    $advert = '';
  }
  else {
    $return = $matches[0];
    $pcount++;
  }
  return $return;
}

echo $first . preg_replace_callback($regexp, 'replacement_callback', $second);

【讨论】:

  • @DebajyotiDas ~ 你运行的是什么版本的 PHP?除非您运行的是 5.3 或更高版本,否则您将无法支持 anonymous callbacks。如果是这样,您应该真正升级,但这不是世界末日,您可能可以使用命名函数。 PS。键盘链接是 404 .. 不知道您遇到了什么错误,因为该代码适用于我的本地设置,因此我无法提供进一步的建议。
  • @DebajyotiDas 键盘运行 PHP 版本 5.2.5。因此错误的原因。以下应该适用于旧版本的 PHP ~ codepad.org/Fj56s6Rv
  • @DebajyotiDas ~ 两个原因。首先是我忘记在最后一个键盘中将函数名称包装在一个字符串中——Doh! -- 还有就是上面的代码只检查了后半部分的内容。您的测试后半部分没有可以放置广告的位置,因此它失败了。这是一个修改后的版本,它使用了剩余内容的 80%,而不是后半部分。 codepad.org/yQ8RY1yI
  • 最后一次非常感谢。您能否稍微修改一下,使其不仅适用于&lt;img ,还适用于&lt;h1&gt;&lt;h2&gt;&lt;h3&gt;&lt;h4&gt;。注意:标题标签不在&lt;p&gt; ... &lt;/p&gt;
  • 我们实际上可以确保广告始终被 2 个段落包围。我们的标题标签、视频嵌入等不会干扰广告
【解决方案2】:

你可以试试这个:

    <?php
  $ad_code = 'SOME SCRIPT HERE';

  // Your code.
  $content = apply_filters('the_content', $post->post_content);

  // Split the content at the <p> tags.
  $content = explode ('<p>', $content);

  // Find the mid of the article.
  $content_length = count($content);
  $content_mid = floor($content_length / 2);

  // Save no image p's index.
  $last_no_image_p_index = NULL;

  // Loop beginning from the mid of the article to search for images.
  for ($i = $content_mid; $i < $content_length; $i++) {
    // If we do not find an image, let it go down.
    if (stripos($content[$i], '<img') === FALSE) {
      // In case we already have a last no image p, we check 
      // if it was the one right before this one, so we have
      // two p tags with no images in there.
      if ($last_no_image_p_index === ($i - 1)) {
        // We break here.
        break;
      }
      else {
        $last_no_image_p_index = $i;
      }
    }
  }

  // If no none image p tag was found, we use the last one.
  if (is_null($last_no_image_p_index)) {
    $last_no_image_p_index = ($content_length - 1);
  }

  // Add ad code here with trailing <p>, so the implode later will work correctly.
  $content = array_slice($content, $last_no_image_p_index, 0, $ad_code . '</p>');

  $content = implode('<p>', $content);
?>

它会尝试从文章中间找到广告的位置,如果找不到,则将广告放在末尾。

问候 func0der

【讨论】:

    【解决方案3】:

    我认为这会奏效:

    首先分解段落,然后你必须循环它并检查是否在其中找到 img。 如果你在里面找到它,你试试下一个。

    将此视为伪代码,因为它未经测试。你也必须做一个循环,代码中的 cmets :) 抱歉,如果它包含错误,它是用记事本编写的。

    <?php
    $i = 0; // counter
    $arrBoolImg = array(); // array for the paragraph booleans
    
    $content = apply_filters('the_content', $post->post_content);
    
    $contents = str_replace ('<p>', '<explode><p>', $content); // here we add a custom tag, so we can explode
    $contents = explode ('<explode>', $contents); // then explode it, so we can iterate the paragraphs
    
    // fill array with boolean array returned
    $arrBoolImg = hasImages($contents);
    $halfway_mark = ceil(count($contents) / 2);
    
    /* 
        TODO (by you):
        ---
        When you have $arrBoolImg filled, you can itarate through it.
        You then simply loop from the middle of the array $contents (plural), that is exploded from above.
        The startingpoing for your loop is the middle, the upper bounds is the +2 or what ever :-)
        Then you simply insert your magic.. And then glue it back together, as you did before.
        I think this will work. even though the code may have some bugs, since I wrote it in Notepad.
    */
    
    
    
    
    
    
    function hasImages($contents) {
    /* 
    This function loops through the $contents array and checks if they have images in them
    The return value, is an array with boolean values, so one can iterate through it.
    */
    $arrRet = array(); // array for the paragraph booleans
    
    if (count($content)>=1) {
        foreach ($contents as $v) { // iterate the content
        if (strpos($v, '<img') === false) { // did not find img
            $arrRet[$i] = false;
            }
            else {              // found img
            $arrRet[$i] = true; 
        }
        $i++;
        } // end for each loop
        return $arrRet;
    } // end if count
    } // end hasImages func
    
    ?>
    

    【讨论】:

      【解决方案4】:

      [这只是一个想法,我没有足够的声誉来评论......]

      在调用@Olavxxx 的方法并填充您的布尔数组后,您可以从中间开始以交替方式循环遍历该数组:假设您的数组有8 个条目长。用你的方法计算中间得到 4。所以你检查值 4 + 3 的组合,如果这不起作用,你检查 4 + 5,然后是 3 + 2,...

      所以你的循环看起来有点像

      $middle = ceil(count($content) / 2);
      $i = 1;
      while ($i <= $middle) {
        $j = $middle + (-1) ^ $i * $i;
        $k = $j + 1;
      
        if (!$hasImagesArray[$j] && !$hasImagesArray[$k])
          break; // position found
      
        $i++;
      }
      

      您可以实施进一步的约束,以确保添加不会在文章中显示在上方或下方...

      请注意,您还需要注意数组太短等特殊情况,以防止出现 IndexOutOfBounds-Exceptions。

      【讨论】:

        猜你喜欢
        • 2020-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-11
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        • 1970-01-01
        相关资源
        最近更新 更多