我使用以下代码在我的内容中放置一些广告代码。
<?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个广告(包含广告的<p>...</p>
不应包含图片或嵌入的视频)。
我想避免使用jQuery。
我的用例示例......
答案 0 :(得分:5)
以下是我对问题的处理方法。很抱歉发布有点迟了(并且错过了赏金:-(),但这是一个忙碌的一周,所以我做了一切都是点点滴滴。
QUICK RUNDOWN
我没有删除第一段中的附件。我不明白为什么内容必须为广告而被破坏
我在代码中进行了大量检查,以确保广告仅插入文本段落之间。仅文本段落被视为不包含img,li和ul标签的段落
我已正确记录每个代码块,因此您可以轻松完成每个部分。如有必要,我还添加了todo
个doc块,您需要注意
我已使用wptexturize
将p标签应用于the_content
。每个双重换行构成一个段落
根据需要修改并使用此代码。我已经对它进行了测试,因此我身上没有错误。
这是代码。希望这对你有用。 * PS!所有这些都进入了你的functions.php。您的模板文件不需要任何其他代码或模块
<?php
add_filter( 'the_content', 'so_25888630_ad_between_paragraphs' );
function so_25888630_ad_between_paragraphs($content){
/**-----------------------------------------------------------------------------
*
* @author Pieter Goosen <http://stackoverflow.com/users/1908141/pieter-goosen>
* @return Ads in between $content
* @link http://stackoverflow.com/q/25888630/1908141
*
* Special thanks to the following answers on my questions that helped me to
* to achieve this
* - http://stackoverflow.com/a/26032282/1908141
* - http://stackoverflow.com/a/25988355/1908141
* - http://stackoverflow.com/a/26010955/1908141
* - http://wordpress.stackexchange.com/a/162787/31545
*
*------------------------------------------------------------------------------*/
if( in_the_loop() ){ //Simply make sure that these changes effect the main query only
/**-----------------------------------------------------------------------------
*
* wptexturize is applied to the $content. This inserts p tags that will help to
* split the text into paragraphs. The text is split into paragraphs after each
* closing p tag. Remember, each double break constitutes a paragraph.
*
* @todo If you really need to delete the attachments in paragraph one, you want
* to do it here before you start your foreach loop
*
*------------------------------------------------------------------------------*/
$closing_p = '</p>';
$paragraphs = explode( $closing_p, wptexturize($content) );
/**-----------------------------------------------------------------------------
*
* The amount of paragraphs is counted to determine add frequency. If there are
* less than four paragraphs, only one ad will be placed. If the paragraph count
* is more than 4, the text is split into two sections, $first and $second according
* to the midpoint of the text. $totals will either contain the full text (if
* paragraph count is less than 4) or an array of the two separate sections of
* text
*
* @todo Set paragraph count to suite your needs
*
*------------------------------------------------------------------------------*/
$count = count( $paragraphs );
if( 4 >= $count ) {
$totals = array( $paragraphs );
}else{
$midpoint = floor($count / 2);
$first = array_slice($paragraphs, 0, $midpoint );
if( $count%2 == 1 ) {
$second = array_slice( $paragraphs, $midpoint, $midpoint, true );
}else{
$second = array_slice( $paragraphs, $midpoint, $midpoint-1, true );
}
$totals = array( $first, $second );
}
$new_paras = array();
foreach ( $totals as $key_total=>$total ) {
/**-----------------------------------------------------------------------------
*
* This is where all the important stuff happens
* The first thing that is done is a work count on every paragraph
* Each paragraph is is also checked if the following tags, a, li and ul exists
* If any of the above tags are found or the text count is less than 10, 0 is
* returned for this paragraph. ($p will hold these values for later checking)
* If none of the above conditions are true, 1 will be returned. 1 will represent
* paragraphs that qualify for add insertion, and these will determine where an ad
* will go
* returned for this paragraph. ($p will hold these values for later checking)
*
* @todo You can delete or add rules here to your liking
*
*------------------------------------------------------------------------------*/
$p = array();
foreach ( $total as $key_paras=>$paragraph ) {
$word_count = count(explode(' ', $paragraph));
if( preg_match( '~<(?:img|ul|li)[ >]~', $paragraph ) || $word_count < 10 ) {
$p[$key_paras] = 0;
}else{
$p[$key_paras] = 1;
}
}
/**-----------------------------------------------------------------------------
*
* Return a position where an add will be inserted
* This code checks if there are two adjacent 1's, and then return the second key
* The ad will be inserted between these keys
* If there are no two adjacent 1's, "no_ad" is returned into array $m
* This means that no ad will be inserted in that section
*
*------------------------------------------------------------------------------*/
$m = array();
foreach ( $p as $key=>$value ) {
if( 1 === $value && array_key_exists( $key-1, $p ) && $p[$key] === $p[$key-1] && !$m){
$m[] = $key;
}elseif( !array_key_exists( $key+1, $p ) && !$m ) {
$m[] = 'no-ad';
}
}
/**-----------------------------------------------------------------------------
*
* Use two different ads, one for each section
* Only ad1 is displayed if there is less than 4 paragraphs
*
* @todo Replace "PLACE YOUR ADD NO 1 HERE" with your add or code. Leave p tags
* @todo I will try to insert widgets here to make it dynamic
*
*------------------------------------------------------------------------------*/
if( $key_total == 0 ){
$ad = array( 'ad1' => '<p>PLACE YOUR ADD NO 1 HERE</p>' );
}else{
$ad = array( 'ad2' => '<p>PLACE YOUR ADD NO 2 HERE</p>' );
}
/**-----------------------------------------------------------------------------
*
* This code loops through all the paragraphs and checks each key against $mail
* and $key_para
* Each paragraph is returned to an array called $new_paras. $new_paras will
* hold the new content that will be passed to $content.
* If a key matches the value of $m (which holds the array key of the position
* where an ad should be inserted) an add is inserted. If $m holds a value of
* 'no_ad', no ad will be inserted
*
*------------------------------------------------------------------------------*/
foreach ( $total as $key_para=>$para ) {
if( !in_array( 'no_ad', $m ) && $key_para === $m[0] ){
$new_paras[key($ad)] = $ad[key($ad)];
$new_paras[$key_para] = $para;
}else{
$new_paras[$key_para] = $para;
}
}
}
/**-----------------------------------------------------------------------------
*
* $content should be a string, not an array. $new_paras is an array, which will
* not work. $new_paras are converted to a string with implode, and then passed
* to $content which will be our new content
*
*------------------------------------------------------------------------------*/
$content = implode( ' ', $new_paras );
}
return $content;
}
编辑
来自您的评论:
您应该使用以下代码来调试<pre><?php var_dump($NAME_OF_VARIABLE); ?></pre>
。对于您的第一个问题,我将在此行?><pre><?php var_dump($paragraphs); ?></pre><?php
之后使用$paragraphs = explode( $closing_p, wpautop($content) );
来准确了解内容是如何拆分的。这样可以让您了解内容是否正确分割。
也可以在此行?><pre><?php var_dump($p); ?></pre><?php
之后使用$p = array();
来检查特定段落的值。请记住,带有img,li和ul标签的段落应该有一个0
,段落少于10个单词。其余的应该是1
编辑 - &gt;解决了剥离段落的问题。谢谢你指出这个漏洞给我。从未意识到这一点我已经更新了代码,所以只需复制并粘贴它
编辑2
请注意,您无法使用所使用的在线工具测试代码。这并不是the_content()
输出内容的真实反映。您在使用在线工具看到的输出会被过滤并标记为the_content()
,然后再发送到屏幕。如果您使用Google Chrome等浏览器检查输出,则会看到正确应用了p标记。
我还在代码
中更改了带有image标签的a标签答案 1 :(得分:3)
使用你给我的示例代码,这是我能做的最好的,那里有太多的图像,你需要一个天才来找出你的要求所需的逻辑,但尝试它可能不会离得太远了。你需要php 5.5。
需要注意几点:
1.它将段落标识为包含在p个元素中,而不是在视觉段落中
2.如果p元素存在于其他元素中,它也会将它们识别为段落。第一个广告就是一个例子。避免在块引用,列表等中使用p,它不是必需的,而是使用跨度,div作为文本
3.我在__construct中注释了一个调用函数的行,取消注释以插入第二个图像。这实际上运作良好但你的内容有很多p元素,其中的数据分为多个p,这不太可能是实际内容的一个因素。
4.它在第1段+第2段中搜索图像并将其删除。
$content = apply_filters('the_content', get_the_content() );
class adinsert {
var $content;
var $paragraphs;
var $ad_pos1=2;
var $ad_pos2;
var $ad_pos3;
var $ad= '<h1>ad position here</h1>';
public function __construct($content) {
if(!$content)
return $content;
$this->set_content($content);
$this->paragrapherize(2);
$this->paragraph_numbers();
$this->get_first_pos();
$this->paragrapherize();
$this->paragraph_numbers();
$this->find_images();
$this->find_ad_pos();
$this->insert_ads();
}
public function echo_content(){
echo $this->content;
}
private function insert_ads() {
if($this->ad_pos2 && $this->ad_pos2 != 'end'):
$posb= $this->ad_pos2;
$this->content=substr_replace($this->content,$this->ad,$posb ,0);
else:
$this->content.= $this->ad;
endif;
//comment the below line to remove last image insertion
$this->content.= $this->ad;
}
private function get_first_pos() {
$i=0;
foreach($this->paragraphs as $key=>$data):
if($i==0):
$length= $data['end']-$data['start'];
$string= substr($this->content, $data['start'],$length);
$newkey= $key+1;
$lengthb= $this->paragraphs[$newkey]['end']-$this->paragraphs[$newkey]['start'];
$stringb= substr($this->content, $this->paragraphs[$newkey]['start'],$lengthb);
$wcount= count(explode(' ', $string));
if( preg_match('/(<img[^>]+>)/i', $string, $image) ):
$newstring=preg_replace('/(<img[^>]+>)/i', '', $string);
if($wcount>10):
$newstring.=$this->ad;
$this->ad_pos1=1;
$this->content=str_replace($string,$newstring,$this->content);
endif;
else:
if($wcount>10) :
$newstring=$string.$this->ad;
echo $newstring;
$this->ad_pos1=1;
//$this->content=str_replace($string,$newstring,$this->content);
$this->content= preg_replace('~'.$string.'~', $newstring, $this->content, 1);
endif;
endif;
if( preg_match('/(<img[^>]+>)/i', $stringb, $imageb) ):
$newstringb=preg_replace('/(<img[^>]+>)/i', '', $stringb);
if($wcount<10) :
$newstringb.=$this->ad;
$this->ad_pos1=2;
$this->content=str_replace($stringb,$newstringb,$this->content);
endif;
else:
if($wcount<10) :
$newstring=$stringb.$this->ad;
$this->ad_pos1=2;
$this->content=str_replace($stringb,$newstringb,$this->content);
endif;
endif;
else:
break;
endif;
$i++;
endforeach;
}
private function find_ad_pos() {
$remainder_images= $this->paragraph_count;
if($remainder_images < $this->ad_pos1 + 3):
$this->ad_pos2='end';
else:
foreach($this->paragraphs as $key=>$data):
$p[]=$key;
endforeach;
unset($p[0]);
unset($p[1]);
$startpos= $this->ad_pos1 + 2;
$possible_ad_positions= $remainder_images - $startpos;
//figure out half way
if($remainder_images < 3): //use end pos
$pos1= $startpos;
$pos1=$this->getclosestkey($pos1, $p);
else: // dont use end pos
$pos1= ($remainder_images/2)-1;
$pos1= $this->getclosestkey($pos1, $p);
endif;
$this->ad_pos2= $this->paragraphs[$pos1]['end'];
endif;
}
private function getclosestkey($key, $keys) {
$close= 0;
foreach($keys as $item): //4>4
if($close == null || $key - $close > $item - $key ) :
$close = $item;
endif;
endforeach;
return $close;
}
private function find_images() {
foreach($this->paragraphs as $item=>$key):
$length= $key['end']-$key['start'];
$string= substr($this->content, $key['start'],$length);
if(strpos($string,'src')!==false && $item !=0 && $item !=1):
//unset the number, find start in paragraphs array + 1 after
unset($this->paragraphs[$item]);
$nextitem= $item+1;
$previtem= $item-1;
unset($this->paragraphs[$nextitem]);
unset($this->paragraphs[$previtem]);
endif;
endforeach;
}
private function paragraph_numbers() {
$i=1;
foreach($this->paragraphs as $item):
$i++;
endforeach;
$this->paragraph_count=$i;
}
private function paragrapherize($limit=0) {
$current_pos=0;
$i=0;
while( strpos($this->content, '<p', $current_pos) !== false ):
if($limit && $i==$limit)
break;
if($i==105) {
break;
}
if($i!=0) {
$current_pos++;
}
$paragraph[$i]['start']=strpos($this->content, '<p', $current_pos);//1
//looking for the next time a /p follows a /p so is less than the next position of p
$nextp= strpos($this->content, '<p', $paragraph[$i]['start']+1); //14 failing on next???
$nextendp= strpos($this->content, '</p>', $current_pos);//22
if($nextp>$nextendp)://NO
$paragraph[$i]['end']=$nextendp;
if( ($nextendp - $paragraph[$i]['start']) < 80 ):
unset($paragraph[$i]);
endif;
$current_pos= $nextendp;
$i++;
else:
$startipos = $nextendp;
$b=0;
do {
if($b==100){
break;
}
$nextp= strpos($this->content, '<p', $startipos); //230
$nextendp= strpos($this->content, '</p>', $startipos+1);//224
if($nextp>$nextendp) {
$paragraph[$i]['end']=$nextendp;
$current_pos= $nextendp;
$i++;
} else {
$startipos = $nextendp+1;
}
$b++;
} while ($nextp < $nextendp );
endif;
endwhile;
$this->paragraphs= $paragraph;
}
public function set_content($content) {
$this->content= $content;
}
}
$newcontent= new adinsert($content);
然后您要输出内容
<?php echo $newcontent->echo_content(); ?>
答案 2 :(得分:2)
这是一个解决方案。它不是完全程序化的,但我之前已经完成了它,它会工作。基本上,使用&#34;短代码&#34;。完全以编程方式执行此操作的问题在于,如果具有内嵌图像,视频等的文章的流量会导致广告展示位置看起来非常糟糕,那么找不到好的方法。相反,请使用短代码设置CMS,以便编辑可以将广告放在文章中的最佳位置。
E.g。
<p>Bacon ipsum dolor sit amet short ribs tenderloin venison pastrami meatloaf kevin, shoulder meatball landjaeger pork corned beef turkey salami frankfurter jerky. Pork loin bresaola porchetta strip steak meatball t-bone andouille chuck chicken shankle shank tongue. Hamburger flank kevin short ribs. Pork loin landjaeger frankfurter corned beef, fatback salami short loin ground round biltong.</p>
[ad_block]
<p>Pastrami jerky drumstick swine ribeye strip steak pork belly kevin tail rump pancetta capicola. Meatloaf doner porchetta, rump tenderloin t-bone biltong pork belly. Porchetta boudin ham ribeye frankfurter flank short loin, drumstick pork loin filet mignon chuck fatback. Strip steak jowl capicola ham hock turducken biltong ground round filet mignon venison prosciutto chuck pork. Venison ribeye fatback kielbasa, ball tip turducken capicola drumstick sausage pancetta boudin turkey ham strip steak corned beef.</p>
然后,使用PHP str_replace
,您只需将ad_block短代码替换为您广告的HTML。
E.g。
echo str_replace('[ad_block]', $ad_block_html, $content);
答案 3 :(得分:2)
我做了一些返工,这就是我最终得到的。 随意测试并给我一些反馈。
class Advertiser
{
/**
* All advertises to place
*
* @access private
* @var array
*/
private $ads = array();
/**
* The position behind the </p> element nearest to the center
*
* @access private
* @var int
*/
private $center = null;
/**
* The content to parse
*
* @access private
* @var string
*/
private $content = null;
/**
* Constructor method
*
* @access public
* @param string $content the content to parse (optional)
* @param array $ads all advertises to place (optional)
* @return object itself as object
*/
public function __construct ($content = null, $ads = array())
{
if (count($ads)) $this->ads = $ads;
if ($content) $this->setContent($content);
return $this;
}
/**
* Calculates and sets the position behind the </p> element nearest to the center
*
* @access public
* @return object the position behind the </p> element nearest to the center
*/
public function calcCenter ()
{
$content = $this->content;
if (!$content) return $this;
$center = ceil(strlen($content)/2);
$rlpos = strripos(substr($content, 0, $center), '</p>');
$rrpos = stripos($content, '</p>', $center);
$this->center = 4 + ($center-$rlpos <= $rrpos-$center ? $rlpos : $rrpos);
return $this;
}
/**
* Places the first ad
*
* @access public
* @param string $ad optional; if not specified, take the internally setted ad
* @return object itself as object
*/
public function placeFirstAd ($ad = null)
{
$ad = $ad ? $ad : $this->ads[0];
$content = $this->content;
if (!$content || !$ad) return $this;
// the position before and after the first paragraph
$pos1 = strpos($content, '<p');
$pos2 = strpos($content, '</p>') + 4;
// place ad
$content = substr($content, 0, $pos2) . $ad . substr($content, $pos2);
// strip images
$content = substr($content, 0, $pos1) . preg_replace('#<img(?:\s.*?)?/?>#i', '', substr($content, $pos1, $pos2)) . substr($content, $pos2);
$this->content = $content;
return $this;
}
/**
* Places the second ad
*
* @access public
* @param string $ad optional; if not specified, take the internally set ad
* @return object itself as object
*/
public function placeSecondAd ($ad = null)
{
$ad = $ad ? $ad : $this->ads[1];
$content = $this->content;
if (!$content || !$ad) return $this;
$center = $this->center;
// place ad
$content = substr($content, 0, $center) . $ad . substr($content, $center);
$this->content = $content;
return $this;
}
/* Getters */
/**
* Gets the content in it's current state
*
* @access public
* @return string the content in it's current state
*/
public function getContent ()
{
return $this->content;
}
/* Setters */
/**
* Sets the content
*
* @access public
* @param string $content the content to parse
* @return object itself as object
*/
public function setContent ($content)
{
$this->content = $content;
$this->calcCenter();
return $this;
}
/**
* Sets the first ad
*
* @access public
* @param string $ad the ad
* @return object itself as object
*/
public function setFirstAd ($ad)
{
if ($ad) $this->ad[0] = $ad;
return $this;
}
/**
* Sets the second ad
*
* @access public
* @param string $ad the ad
* @return object itself as object
*/
public function setSecondAd ($ad)
{
if ($ad) $this->ad[1] = $ad;
return $this;
}
}
用法示例:
$first_ad = 'bacon';
$second_ad = 'ham';
$content = apply_filters('the_content', $post->post_content);
$advertiser = new Advertiser($content);
$advertiser->placeFirstAd($first_ad);
//$advertiser-> placeSecondAd($second_ad);
$advertised_content = $advertiser->getContent();
您可以将placeSecondAd()注释掉,或将其替换为您的工作函数。
答案 4 :(得分:1)
这是一种聪明的方式:
$content = "<p>A</p><p>B</p><p>C</p><p>D</p>";
$pos = 2;
$content = preg_replace('/<p>/', '<helper>', $content, $pos + 1); //<helper>A</p><helper>B</p><helper>C</p><p>D</p>
$content = preg_replace('/<helper>/', '<p>', $content, $pos); //<p>A</p><p>B</p><helper>C</p><p>D</p>
$content = str_replace("<helper>", "<p>ad</p><p>", $content); //<p>A</p><p>B</p><p>ad</p><p>C</p><p>D</p>
这是一个完整的功能:
function insertAd($content, $ad, $pos = 0){
// $pos = 0 means randomly position in the content
$count = substr_count($content, "<p>");
if($count == 0 or $count <= $pos){
return $content;
}
else{
if($pos == 0){
$pos = rand (1, $count - 1);
}
$content = preg_replace('/<p>/', '<helper>', $content, $pos + 1);
$content = preg_replace('/<helper>/', '<p>', $content, $pos);
$content = str_replace('<helper>', $ad . "\n<p>", $content);
return $content;
}
}
答案 5 :(得分:0)
好的,这是一个让你(可能)更接近你所要求的完全程序化方式的方向的想法......
使用像http://simplehtmldom.sourceforge.net/这样的HTML DOM解析器来解析每篇文章。使用这个,你理论上应该能够挑选出所有的段落标签,然后根据你的数学将广告块插入到正确的广告块之间。
$html = str_get_html($content);
$paragraphs_arr = $html->find('p'); //Returns all paragraphs
$halfway_mark = ceil(count($paragraphs_arr) / 2);
$halfway_paragraph = $paragraphs_arr[$halfway_mark];
// Somewhere here now you just have to figure out how to inject the ad right after the halfway paragraph.
E.g.
$p_content = $halfway_paragraph->innertext();
$p_content = $p_content."</p><p><!-- Ad --></p>"; // Force close the tag as we're in the innertext.
$halfway_paragraph->innertext($p_content);
这会让您更接近您尝试做的事情吗?
答案 6 :(得分:-1)
使用
strip_tags('contnet','like <p>');
答案 7 :(得分:-2)
$content = apply_filters('the_content', $post->post_content);
// $middle will mark the center of the $content based on number of characters and is aware of words and will therefor mark the middle to the nearest space. +1 is added to then remove the whitespace at the end of the string.
$middle = strrpos(substr($content, 0, floor(strlen($content) / 2)), ' ') + 1;
// $first_half will substring the text to the first half based on where $middle says to split it
$first_half= substr($text, 0, $middle);
// $second_half substrings the text to the seconf half based on where $first_half is split.
$second_half= substr($text, $middle);
echo $first_half.'...';
echo ' YOUR ADS CODE';
echo $second_half;