PHP preg_match_all search replace problem

Discussion in 'PHP' started by electroze, Jun 29, 2012.

  1. #1
    Hi, I have code that's supposed to search and replace searched words with a bold. (like how Google highlights their searched keywords after a search).

    But I'm having a hard time with preg_match_all, and the regex word boundary, which is this line:

    preg_match_all("/\w*$oneword\w*/i", $haystack, $matches);

    You can see I'm trying to make all instances of 'children of israel' bold and not partial words, but I think it's somehow expanding to the entire sentence? Sometimes it works and sometimes not, if anyone sees the problem in my code, I'd be grateful to know this...

    <?php 
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); 
    error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
    
    $bible = array("Numbers 8:19" => "And I have given the Levites as a gift to Aaron and to his sons from among the children of Israel, to do the service of the children of Israel in the tabernacle of the congregation, and to make an atonement for the children of Israel: that there be no plague among the children of Israel, when the children of Israel come nigh unto the sanctuary.",
    
    "Joshua 22:11" => "And the children of Israel heard say, Behold, the children of Reuben and the children of Gad and the half tribe of Manasseh have built an altar over against the land of Canaan, in the borders of Jordan, at the passage of the children of Israel.",
    
    "2 Samuel 21:2" => "And [the] king called the Gibeonites, and said unto them; (now the Gibeonites were not of the children of Israel, but of the remnant of the Amorites; and the children of Israel had sworn unto them: and Saul sought to slay them in his zeal to the children of Israel and Judah.",
    
    "Joshua 22:33" => "And [the] thing pleased the children of Israel; and the children of Israel blessed God, and did not intend to go up against them in battle, to destroy the land wherein the children of Reuben and Gad dwelt.",
    
    "Judges 20:13" => "Now therefore deliver us the men, the children of Belial, which are in Gibeah, that we may put them to death, and put away evil from Israel. But the children of Benjamin would not hearken to the voice of their brethren the children of Israel:");
    
    
    //this is the search query- to search and replace this with bold
    //try different words
    
    $word = "children of israel";
    //$word = "Gibeonites";
    //$word = "children of Belial";
    
    
    foreach($bible as $row){
    
    echo "<br /><br />";
    
    $vtextwithhighlight = str_replace("[","<em>",$row);
    		$vtextwithhighlight = str_replace("]","</em>",$vtextwithhighlight);
    $vtextwithhighlighttwo = $vtextwithhighlight;
    $haystack = $vtextwithhighlighttwo;
    
    $wordsArray = explode(' ', $word); 
        foreach($wordsArray as $oneword) { 
            if(strlen(trim($oneword)) != 0) 
    preg_match_all("/\w*$oneword\w*/i", $haystack, $matches);		
        if (is_array($matches[0]) && count($matches[0]) >= 1) {
            foreach ($matches[0] as $match) {
                $haystack = str_replace($match, '<strong>'.$match.'</strong>', $haystack);
            }
        }		
    
    		}
    echo $haystack;
    }
    
    ?>
    PHP:
     
    electroze, Jun 29, 2012 IP
  2. NetStar

    NetStar Notable Member

    Messages:
    2,471
    Likes Received:
    541
    Best Answers:
    21
    Trophy Points:
    245
    #2
    You could just loop through the array then use a regex substitution replacing all strings matching $word wrapped with the strong tags like so:

    
    <?php
    
    $bible = array("Numbers 8:19" => "And I have given the Levites as a gift to Aaron and to his sons from among the children of Israel, to do the service of the children of Israel in the tabernacle of the congregation, and to make an atonement for the children of Israel: that there be no plague among the children of Israel, when the children of Israel come nigh unto the sanctuary.",
    
    "Joshua 22:11" => "And the children of Israel heard say, Behold, the children of Reuben and the children of Gad and the half tribe of Manasseh have built an altar over against the land of Canaan, in the borders of Jordan, at the passage of the children of Israel.",
    
    "2 Samuel 21:2" => "And [the] king called the Gibeonites, and said unto them; (now the Gibeonites were not of the children of Israel, but of the remnant of the Amorites; and the children of Israel had sworn unto them: and Saul sought to slay them in his zeal to the children of Israel and Judah.",
    
    "Joshua 22:33" => "And [the] thing pleased the children of Israel; and the children of Israel blessed God, and did not intend to go up against them in battle, to destroy the land wherein the children of Reuben and Gad dwelt.",
    
    "Judges 20:13" => "Now therefore deliver us the men, the children of Belial, which are in Gibeah, that we may put them to death, and put away evil from Israel. But the children of Benjamin would not hearken to the voice of their brethren the children of Israel:");
    
    
    $word = "children of israel";
    
    foreach ($bible as $bible_key => $bible_value)
    {
       $bible_value = str_replace("[", "<em>", $bible_value);
       $bible_value = str_replace("]", "</em>", $bible_value);
       $bible_value = preg_replace("/$word/i", "<strong>$word</strong>", $bible_value);
    
       $bible[$bible_key] = $bible_value;
       
       print $bible[$bible_key] . "<br /><br />\n";
    }
    
    ?>
    
    PHP:
    Test that out and see if it's what you're looking to do.

    It prints:

    
    And I have given the Levites as a gift to Aaron and to his sons from among the <strong>children of israel</strong>, to do the service of the <strong>children of israel</strong> in the tabernacle of the congregation, and to make an atonement for the <strong>children of israel</strong>: that there be no plague among the <strong>children of israel</strong>, when the <strong>children of israel</strong> come nigh unto the sanctuary.<br /><br />
    And the <strong>children of israel</strong> heard say, Behold, the children of Reuben and the children of Gad and the half tribe of Manasseh have built an altar over against the land of Canaan, in the borders of Jordan, at the passage of the <strong>children of israel</strong>.<br /><br />
    And <em>the</em> king called the Gibeonites, and said unto them; (now the Gibeonites were not of the <strong>children of israel</strong>, but of the remnant of the Amorites; and the <strong>children of israel</strong> had sworn unto them: and Saul sought to slay them in his zeal to the <strong>children of israel</strong> and Judah.<br /><br />
    And <em>the</em> thing pleased the <strong>children of israel</strong>; and the <strong>children of israel</strong> blessed God, and did not intend to go up against them in battle, to destroy the land wherein the children of Reuben and Gad dwelt.<br /><br />
    Now therefore deliver us the men, the children of Belial, which are in Gibeah, that we may put them to death, and put away evil from Israel. But the children of Benjamin would not hearken to the voice of their brethren the <strong>children of israel</strong>:<br /><br />
    
    HTML:
     
    NetStar, Jun 29, 2012 IP
  3. electroze

    electroze Active Member

    Messages:
    179
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    60
    #3
    Great, thank you. The script needs to also match the words displayed separately and in different order too, such as 'Israel children' or 'OF kind CHILDREN from the land of 'ISRAEL' - it's supposed to bold those words too, for example.

    In the code I have the explode and loop to do that, but I think my word boundary is wrong? If anyone knows why it may not be working, please let me know!
     
    electroze, Jun 30, 2012 IP
  4. NetStar

    NetStar Notable Member

    Messages:
    2,471
    Likes Received:
    541
    Best Answers:
    21
    Trophy Points:
    245
    #4
    You could loop through each word in $word and use a preg_replace to add strong tags.

    
    <?php
    
    $bible = array("Numbers 8:19" => "And I have given the Levites as a gift to Aaron and to his sons from among the children of Israel, to do the service of the children of Israel in the tabernacle of the congregation, and to make an atonement for the children of Israel: that there be no plague among the children of Israel, when the children of Israel come nigh unto the sanctuary.",
    
    "Joshua 22:11" => "And the children of Israel heard say, Behold, the children of Reuben and the children of Gad and the half tribe of Manasseh have built an altar over against the land of Canaan, in the borders of Jordan, at the passage of the children of Israel.",
    
    "2 Samuel 21:2" => "And [the] king called the Gibeonites, and said unto them; (now the Gibeonites were not of the children of Israel, but of the remnant of the Amorites; and the children of Israel had sworn unto them: and Saul sought to slay them in his zeal to the children of Israel and Judah.",
    
    "Joshua 22:33" => "And [the] thing pleased the children of Israel; and the children of Israel blessed God, and did not intend to go up against them in battle, to destroy the land wherein the children of Reuben and Gad dwelt.",
    
    "Judges 20:13" => "Now therefore deliver us the men, the children of Belial, which are in Gibeah, that we may put them to death, and put away evil from Israel. But the children of Benjamin would not hearken to the voice of their brethren the children of Israel:");
    
    
    $word = "children of israel";
    
    
    foreach ($bible as $bible_key => $bible_value)
    {
       $bible_value = str_replace("[", "<em>", $bible_value);
       $bible_value = str_replace("]", "</em>", $bible_value);
       
       foreach (explode(' ', $word) as $keyword)
       {
          $bible_value = preg_replace("/$keyword/i", "<strong>$keyword</strong>", $bible_value);
       }
       
       $bible[$bible_key] = $bible_value;
       
       print $bible[$bible_key] . "<br /><br />\n";
    }
    
    ?>
    
    PHP:
    This will print

    
    And I have given the Levites as a gift to Aaron and to his sons from among the <strong>children</strong> <strong>of</strong> <strong>israel</strong>, to do the service <strong>of</strong> the <strong>children</strong> <strong>of</strong> <strong>israel</strong> in the tabernacle <strong>of</strong> the congregation, and to make an atonement for the <strong>children</strong> <strong>of</strong> <strong>israel</strong>: that there be no plague among the <strong>children</strong> <strong>of</strong> <strong>israel</strong>, when the <strong>children</strong> <strong>of</strong> <strong>israel</strong> come nigh unto the sanctuary.<br /><br />
    And the <strong>children</strong> <strong>of</strong> <strong>israel</strong> heard say, Behold, the <strong>children</strong> <strong>of</strong> Reuben and the <strong>children</strong> <strong>of</strong> Gad and the half tribe <strong>of</strong> Manasseh have built an altar over against the land <strong>of</strong> Canaan, in the borders <strong>of</strong> Jordan, at the passage <strong>of</strong> the <strong>children</strong> <strong>of</strong> <strong>israel</strong>.<br /><br />
    And <em>the</em> king called the Gibeonites, and said unto them; (now the Gibeonites were not <strong>of</strong> the <strong>children</strong> <strong>of</strong> <strong>israel</strong>, but <strong>of</strong> the remnant <strong>of</strong> the Amorites; and the <strong>children</strong> <strong>of</strong> <strong>israel</strong> had sworn unto them: and Saul sought to slay them in his zeal to the <strong>children</strong> <strong>of</strong> <strong>israel</strong> and Judah.<br /><br />
    And <em>the</em> thing pleased the <strong>children</strong> <strong>of</strong> <strong>israel</strong>; and the <strong>children</strong> <strong>of</strong> <strong>israel</strong> blessed God, and did not intend to go up against them in battle, to destroy the land wherein the <strong>children</strong> <strong>of</strong> Reuben and Gad dwelt.<br /><br />
    Now therefore deliver us the men, the <strong>children</strong> <strong>of</strong> Belial, which are in Gibeah, that we may put them to death, and put away evil from <strong>israel</strong>. But the <strong>children</strong> <strong>of</strong> Benjamin would not hearken to the voice <strong>of</strong> their brethren the <strong>children</strong> <strong>of</strong> <strong>israel</strong>:<br /><br />
    
    HTML:
     
    Last edited: Jun 30, 2012
    NetStar, Jun 30, 2012 IP
  5. electroze

    electroze Active Member

    Messages:
    179
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    60
    #5
    Very cool, thanks!

    The only problem now is it will lose the original case, so it might replace a proper uppercase word with a lowercase word, if someone types their search in lowercase, which is common. So if they do that and it matches the beginning of a sentence, or a proper word like Israel, then it's lowercase currently, and not good.
     
    electroze, Jul 1, 2012 IP
  6. NetStar

    NetStar Notable Member

    Messages:
    2,471
    Likes Received:
    541
    Best Answers:
    21
    Trophy Points:
    245
    #6
    Case IN-sensitive: $bible_value = preg_replace("/$keyword/i", "<strong>$keyword</strong>", $bible_value);

    Case Sensitive: $bible_value = preg_replace("/$keyword/", "<strong>$keyword</strong>", $bible_value);


    The "i" modifier of the regular expression is for case insensitivity. Include "i" if you want to match ANY case. Exclude "i" if you want to match the exact case.
     
    NetStar, Jul 2, 2012 IP