WillW
WillW

Reputation: 195

Split HTML in two with PHP

I'm trying to split a string of text in half, being mindful to not:

To give you a bit of background, I want to take a blog article and inject an advert in the middle of it.

I've hunted around for an answer but the only options I can find on SO suggest stripping all HTML – which isn't an option...

Example:

  $string = "<div class='some-class'>Deasdadlights blasdasde holysadsdto <span>Bri<img src='#'>cable holystone blow the man down</span></div>";
  $length = strlen($string);

  // At this point, something magical needs to split the string being mindful of word breaks and html
  $pieces = array(
    substr( $string, 0, ( $length / 2 ) ),
    substr( $string, ( $length / 2 ), $length )
  );

  echo $pieces[0] . " **Something** " . $pieces[1];

  // <div class="some-class">Deasdadlights blasdasde holysadsdto <spa **something**="" n="">Bri<img src="#">cable holystone blow the man down</spa></div>
  // And there goes the <span> tag :'(

UPDATE

Thank @Naga for the answer! Here's a slightly more expanded version for anyone needing it:

$string = '
  <section class="post_content">
    <p>Often half the battle is ensuring you get the time to respond to your reviews, the other half is remembering that the customer is always right and you should proceed with caution.</p>
    <p>Some simple principles to keep in mind are to be <strong>positive</strong>, <strong>humble</strong>, <strong>helpful</strong>, and <strong>enthusiastic</strong>.</p>
    <p>Some simple principles to keep in mind are to be <strong>positive</strong>, <strong>humble</strong>, <strong>helpful</strong>, and <strong>enthusiastic</strong>.</p>
  </section>
  ';

  $dom = new DOMDocument();
  $dom->preserveWhiteSpace = false;
  libxml_use_internal_errors(true);
  $dom->loadHTML($string);  // $string is the block page full / part html       
  $xpath = new DOMXPath($dom);  
  $obj = $xpath->query('//section[@class="post_content"]'); // assume this is the container div that where you want to inject
  $nodes = $obj->item(0)->childNodes;
  $half = $nodes->length / 2;

  $i = 0;
  foreach( $nodes as $node ) {
    if ( $i === $half ) {
      echo "<div class='insert'></div>";
    }
    echo $node->ownerDocument->saveHTML($node);
    $i ++;
  }

Upvotes: 3

Views: 2138

Answers (1)

Naga
Naga

Reputation: 2168

simply splitting by string length will mess the output html. You need to find find the container of where you want to inject the advert and count the child html nodes then foreach the child notes to reconstruct the html with your advert injection after certain child nodes.

Ex,

        $dom = new DOMDocument();
        $dom->preserveWhiteSpace = false;
        libxml_use_internal_errors(true);
        $dom->loadHTML($html);  // $html is the block page full / part html       
        $xpath = new DOMXPath($dom);  

        $obj = $xpath->query('//div[@class="content"]'); // div[@class="content"] - assume this is the container div that where you want to inject
        var_dump($obj); // you will get all the inner content
        echo $htmlString = $dom->saveHTML($obj->item(0));  // you will have all the inner html
        // after this count the all child nodes and inject your advert and reconstruct render the page.

OR

in simple way, find a constant text tag in middle of the HTML content and replace the tag with your injection + constant text tag.

Ex,

$cons = '<h3 class="heading">Some heading</h3>';
$inject = 'your advert html/text';
$string = str_replace = ($cons, $inject.$cons, $string);

Upvotes: 2

Related Questions