PHP如何在每5的倍数个</p>标签后插入分页字符串
问题根因分析
现有代码的两处核心问题导致无法实现目标:
- 插入判断逻辑写死为
$i == 10,没有做“计数为5的倍数”的条件判断,自然不会在第5、15个段落后面插入标识 - 边修改原字符串边做位置查找的逻辑存在严重偏移问题:每次
substr_replace插入[next]后,整个字符串的长度会增加,后续strpos查找</p>标签的位置基准已经变化,哪怕修改判断条件,也会出现匹配位置错位、重复匹配的问题;同时原代码循环上限写死99、未处理strpos返回false的边界情况,容易出现无限循环匹配第一个标签的问题。
可直接运行的实现方案
方案1:修正原位置匹配逻辑(提前算好所有插入位置,无偏移)
这种思路完全不打乱原始字符串的查找基准,先在原始内容上定位所有</p>标签的位置,筛选出第5、10、15...个标签的位置,再从后往前批量插入内容(从后往前插不会打乱前面的位置坐标),示例代码:
$string = " <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p> <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p> <p>11</p> <p>12</p> <p>13</p> <p>14</p> <p>15</p> <p>16</p> <p>17</p> "; $paginate = '[next]'; // 第一步:在原始字符串上收集所有</p>的位置 $tagPositions = []; $searchOffset = 0; $tagLen = strlen('</p>'); while(($pos = strpos($string, '</p>', $searchOffset)) !== false) { $tagPositions[] = $pos + $tagLen; // 记录标签结束的位置,也就是要插入内容的位置 $searchOffset = $pos + $tagLen; } // 第二步:筛选出序号为5的倍数的标签位置,倒序排列(从后往前插不打乱原坐标) $insertPositions = []; foreach($tagPositions as $index => $pos) { // 因为index从0开始,第n个段落对应index+1 if(($index + 1) % 5 === 0) { $insertPositions[] = $pos; } } rsort($insertPositions); // 第三步:逐位置插入分页标识 foreach($insertPositions as $pos) { $string = substr_replace($string, $paginate, $pos, 0); } echo $string;
方案2:正则回调实现(更简洁,无位置偏移问题)
这种方法不需要手动算坐标,正则引擎会逐次匹配每个</p>标签,通过回调内部的计数器判断插入时机,代码更简洁鲁棒:
$string = " <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p> <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p> <p>11</p> <p>12</p> <p>13</p> <p>14</p> <p>15</p> <p>16</p> <p>17</p> "; $paginate = '[next]'; $count = 0; $string = preg_replace_callback( '/<\/p>/', function($match) use ($paginate, &$count) { $count++; // 每数到5的倍数,就把匹配到的</p>后面追加分页标识 return ($count %5 === 0) ? $match[0] . $paginate : $match[0]; }, $string ); echo $string;
实现效果
两种方案最终输出的内容中,第5、10、15个</p>标签后都会自动追加[next],完全匹配长文章按段落数自动分页的需求,不会出现位置错位的问题。
内容的提问来源于stack exchange,提问作者Ibrahim Ahmad
相关产品推荐
相关产品推荐

