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);