Highlight the difference between two strings in PHP

Viewed 121383

What is the easiest way to highlight the difference between two strings in PHP?

I'm thinking along the lines of the Stack Overflow edit history page, where new text is in green and removed text is in red. If there are any pre-written functions or classes available, that would be ideal.

16 Answers

You were able to use the PHP Horde_Text_Diff package.

However this package is no longer available.

If you want a robust library, Text_Diff (a PEAR package) looks to be pretty good. It has some pretty cool features.

What you are looking for is a "diff algorithm". A quick google search led me to this solution. I did not test it, but maybe it will do what you need.

I have tried a simple approach with two text box and some color styling. Note: my diff checker will only highlight difference in words and not in characters.

    <?php
    $valueOne = $_POST['value'] ?? "";
    $valueTwo = $_POST['valueb'] ?? "" ;
    
    $trimValueOne = trim($valueOne);
    $trimValueTwo = trim($valueTwo);

    $arrayValueOne = explode(" ",$trimValueOne);
    $arrayValueTwo = explode(" ",$trimValueTwo);

    $allDiff = array_merge(array_diff($arrayValueOne, $arrayValueTwo), array_diff($arrayValueTwo, $arrayValueOne));
    if(array_intersect($arrayValueOne,$allDiff) && array_intersect($arrayValueTwo,$allDiff)){

        if(array_intersect($arrayValueOne,$allDiff)){
            $highlightArr = array_intersect($arrayValueOne,$allDiff);
            $highlightArrValue = array_values($highlightArr);
            for ($i=0; $i <count($arrayValueOne) ;$i++) { 
                for ($j=0; $j <count($highlightArrValue) ; $j++) { 
                    if($arrayValueOne[$i] == $highlightArrValue[$j]){
                        $arrayValueOne[$i] = "<span>".$arrayValueOne[$i]."</span>";
                    }
                }
            }
            $strOne = implode(" ",$arrayValueOne);
            echo "<p class = \"one\">{$strOne}</p>";
        }if(array_intersect($arrayValueTwo,$allDiff)){
        $highlightArr = array_intersect($arrayValueTwo,$allDiff);
        $highlightArrValue = array_values($highlightArr);
        for ($i=0; $i <count($arrayValueTwo) ;$i++) { 
            for ($j=0; $j <count($highlightArrValue) ; $j++) { 
                    if($arrayValueTwo[$i] == $highlightArrValue[$j]){
                        $arrayValueTwo[$i] = "<span>".$arrayValueTwo[$i]."</span>";
                    }
                }
        }
        $strTwo = implode(" ",$arrayValueTwo);
        echo "<p class = \"two\">{$strTwo}</p>";
        }
    }elseif(!(array_intersect($arrayValueOne,$allDiff) && array_intersect($arrayValueTwo,$allDiff))){
        if($trimValueOne == $trimValueTwo){
            echo"<p class = \"one green\">$trimValueOne</p></p>";
            echo"<p class = \"two green\">$trimValueTwo</p></p>";
        }
        else{
            echo"<p class = \"one \">$trimValueOne</p></p>";
            echo"<p class = \"two \">$trimValueTwo</p></p>";
        }

    }
?>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <form method="post" action="">
    <textarea type="text" name="value" placeholder="enter first text"></textarea>
    <textarea type="text" name="valueb" placeholder="enter second text"></textarea>
    <input type="submit">
    </form>
</body>
</html>

For those just looking for a very simple function to find characters in string A but not in string B i wrote this quick and very simple function.

function strdiff($a,$b){

    $a = str_split($a);
    $b = str_split($b);

    return array_diff($a,$b);

}

Hi this will help you a lot:

$old_data = "We'll of today's hunt we will find inner zen. You are awesome [TEAM_NAME]! Cleveland has a lot more to offer though, so keep on roaming and find some happiness with Let's Roam!;";
$new_data = "We'll of today's hunt we will find inner zen. Great job today, you are freaking super awesome [TEAM_NAME]! though, so keep roaming Cleveland has a lot more to offer and find happiness on www.letsroam.com!;";

if($old_data) {
  $old_words = explode(" " , $old_data);
  $new_words = explode(" ", $new_data);

  $added_words = array();
  $deleted_words = array();
  $unchanged_words = array();
  foreach($new_words as $new_word) {
      $new_word_index = array_search($new_word, $old_words);
      // if($new_word == "you"){
      //   die_r(array());
      // }
      if( $new_word_index > -1) {
          // word already exists
          array_push($unchanged_words, $new_word);
          unset($old_words[$new_word_index]);
      } else {
          // word does not already exists
          array_push($added_words, $new_word);
      } 
      
   }
 $deleted_words = $old_words;
 $added_word_count = count($added_words);
 $added_word_characters = strlen(implode(" ", $added_words));
}
die_r(array(
  "old_data"=> $old_data,
  "new_data"=> $new_data,
  "unchanged_words"=> $unchanged_words,
  "added_words"=> $added_words,
  "deleted_words"=> $deleted_words,
  "added_word_count"=>$added_word_count,
  "added_word_characters"=>$added_word_characters
));

Related