質問

For testing purposes I've stored in database name of colors which are:

Apple green
Banana yellow
Brick red
Charcoal
Coffee

And I created functions to search and display results with using $_GET and address bar, so far it all works perfectly. So for example if I type to the search form this: ap le ee

My address bar looks like this:

http://test.com/file.php?keywords=ap+le+ee

and my result is obviously Apple green

If I type this: c o or co

My result is: Charcoal and Coffee

At this point I want to upgrade this search engine and highlight in result only those parts that matches with provided keywords so what I want to achieve is this:

If I type: app ee

I want to have in result something like this: <strong>App</strong>le gr<strong>ee</strong>n

and I don't have any idea how to achieve it.

I call my results like this:

$colors = get_colors(isset($_GET['keywords']) ? $_GET['keywords'] : null);
foreach($colors as $color) {
    echo $color['color_name'] . '<br />';
}

If anyone could help me do it, I'll be very grateful, thank you in advance :)

---EDIT--- 10.03.2014 08:34

This is now the code im using:

$colors = get_colors(isset($_GET['keywords']) ? $_GET['keywords'] : null);
foreach($colors as $color) {
    $output = $color['color_name'];

    foreach (explode(' ', $_GET['keywords']) as $term)
        $output = preg_replace('/(?![^<>]*>)'.preg_quote($term,"/").'/i', '<span style="color:red;">$0</span>', $output);

    echo $output . "<br />";
}

Things that work perfect (testing case Banana yellow, Charcoal):

  1. doesnt matter if i type l o or o l both of those will highlight properly in testing cases.

  2. script doesnt fail if i type last letter, i can type ban w and it will properly return highlighted Banana yellow.

The only thing that doesnt work in it is:

  1. if i type bana nana it highlights only bana in Banana yellow

So i believe that right now im looking for solution for overlaping terms to work together that if i type bri ick it should highlight all Brick in Brick red instead of only Bri.

Anyone with ideas how to sort that?

役に立ちましたか?

解決 2

Using @Utkanos suggestion:

foreach($colors as $color) {
    $output = $color['color_name'];
    foreach(explode(' ', $_GET['keywords']) as $term)
        $output = preg_replace('/('.$term.')(?![^>]*>)/i', '<strong>$1</strong>', $output);
    echo  $output .'<br />';
}

You want the result from the preg_match to replace the $term.

Sorry, it's a lot of code for a apparently "simply" problem, but this should do, what you expect:

$colors = array("Apple green",
                "Banana yellow",
                "Brick red",
                "Charcoal",
                "Coffee",
                "Fire red");

$terms = "re e";
$output = "";

foreach($colors as $color) {
    $output = $color;
    $words = array();

    foreach(explode(' ', $terms) as $term) {
        $match = preg_match_all("/(". $term .")/i", $output, $hits, PREG_OFFSET_CAPTURE);

        if($match) {
            $positions = array();
            foreach($hits[1] as $hit) {

                for($i = $hit[1]; $i < strlen($hit[0]) + $hit[1]; $i++) {
                    $positions[] = $i;
                }
                $words[] = array($hits[0][0][0], $positions);

            }
        }
    }

    $positions = array();
    foreach($words as $word) {
        foreach($word[1] as $position)
            $positions[] = $position;
    }

    $positions = array_unique($positions);
    asort($positions);
    $positions = array_values($positions);

    if(count($positions) > 0) {
        $offset = 0;
        $open = false;
        $closed = true;

        $i = $positions[0];
        foreach($positions as $value) {

            if($value != $i AND !$closed) {
                $output = substr_replace($output, "</strong>", $i + $offset, 0);
                $offset += 9;
                $open = false;
                $closed = true;
                $i = $value;
            }

            if(!$open AND $closed) {
                $output = substr_replace($output, "<strong>", $value + $offset, 0);
                $offset += 8;
                $open = true;
                $closed = false;
            }

            $i++;

        }

        if(!$closed)
            $output = substr_replace($output, "</strong>", $positions[count($positions)-1] + $offset +1, 0);
    }


    echo $output ."<br/>";

}

他のヒント

By the look of it you're allowing multiple search terms, separated by space. So I'd loop over the terms and do a replace on the colour before output.

foreach($colors as $color) {
    $output = $color['color_name'];
    foreach(explode(' ', $_GET['keywords']) as $term)
        $output = preg_replace('/'.$term.'(?![^>]*>)/i', '<strong>'.$term.'</strong>', $output);
    echo  preg_replace('/And\b/', 'and', ucwords($output)).'<br />';
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top