omg
omg

Reputation: 139872

How to generate the snippet like those generated by Google with PHP and MySQL?

For example, it just returns the snippet around which the searching keyword exists.

And part of the text is replaced by "...".

Is it possible to achieve that goal with PHP and MySQL?

Upvotes: 6

Views: 6071

Answers (5)

Dmitry S.
Dmitry S.

Reputation: 9

this is my modified function

function excerpt_2($text, $query, $limit_chars_between, $results_divider, $b_highlight_class)
{
    if ((trim($text) === '') || (trim($query) === '')) {
        return false;
    }

    $text = "\n" . chop(trim($text)) . "\n"; // IMPORTANT START/END with "\n" - for search first/last entries

    //words
    $words = join('|', explode(' ', preg_quote(trim($query))));

    //lookahead/behind assertions ensures cut between words
    $s_preg_charset = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
    preg_match_all('#(?<=[' . $s_preg_charset . ']).{0,' . $limit_chars_between . '}((' . $words . ').{0,' . $limit_chars_between . '})+(?=[' . $s_preg_charset . '])#ius', $text, $matches, PREG_OFFSET_CAPTURE);

    $result = $is_text_truncated = false;
    $first_founded_pos = $last_founded_pos = -1;
    $a_results = array();
    
    if (count($matches[0]) > 0) {
        foreach ($matches[0] as $a_line) {
            if ($first_founded_pos < 0) {
                $first_founded_pos = $a_line[1];
            }
            $a_results[] = chop(trim($a_line[0])); //htmlspecialchars($a_line[0], 0, 'UTF-8');
        }

        if (count($a_results)) {
            $result = join(' ' . $results_divider . ' ', $a_results);

            if (($first_founded_pos > $limit_chars_between)) {
                $result = $results_divider . '' . $result;
            }

            $last_el_matches = end($matches);
            $last_founded_pos = $last_el_matches[0][1];

            if (($last_founded_pos + $limit_chars_between) < mb_strlen($text, 'UTF-8')) {
                $result .= $results_divider;
            }

            $is_text_truncated = true;
            $result = preg_replace('#' . $words . '#iu', '<b class="' . $b_highlight_class . '">$0</b>', $result);
        }

    }

    return array(
        'text' => $result,
        'is_text_truncated' => $is_text_truncated,
    );
}

Upvotes: 0

halocursed
halocursed

Reputation: 2485

$snippet = "//mysql query";

function trimmer($updates,$wrds){
    if(strlen($updates)<=$wrds){
        return $updates;
    }else{
    $marker = strrpos(substr($updates,0,$wrds),' ');
    $string = substr(substr($updates,0,$wrds),0,$marker)."...";return $string;
}

echo trimmer($snippet,200); //You can send the snippet string to this function it searches for the last space if string length is greater than 200 and adds "..." to it

This is probably what you want (EDIT):

$string1="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
function trimmer($updates,$wrds,$pos){
    if(strlen($updates)<=$wrds) {
        return $updates;
} else {
        $marker = strrpos(substr($updates,$pos,$wrds),' ');
        $string = substr(substr($updates,$pos,$wrds),0,$marker)."...";
        return $string;
    }
}

$pos = strpos($string1, "dummy");
echo trimmer($string1,100,$pos);

Upvotes: 0

zbycz
zbycz

Reputation: 654

My solution for multiple multiple keywords and multiple occurences (also works for accents case insensitive):

function excerpt($text, $query)
{
//words
$words = join('|', explode(' ', preg_quote($query)));

//lookahead/behind assertions ensures cut between words
$s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
preg_match_all('#(?<=['.$s.']).{1,30}(('.$words.').{1,30})+(?=['.$s.'])#uis', $text, $matches, PREG_SET_ORDER);

//delimiter between occurences
$results = array();
foreach($matches as $line) {
    $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
}
$result = join(' <b>(...)</b> ', $results);

//highlight
$result = preg_replace('#'.$words.'#iu', "<span class=\"highlight\">\$0</span>", $result);

return $result;
}

This is example result for query = "švihov prohlídkám"

Result

Upvotes: 6

Alec Smart
Alec Smart

Reputation: 95900

Modified deceze's function slightly to allow multiple phrases. e.g. your phrase can be "testa testb" and if it does not find testa, then it will go to testb.

function excerpt($text, $phrase, $radius = 100, $ending = "...") { 


         $phraseLen = strlen($phrase); 
       if ($radius < $phraseLen) { 
             $radius = $phraseLen; 
         } 

         $phrases = explode (' ',$phrase);

         foreach ($phrases as $phrase) {
             $pos = strpos(strtolower($text), strtolower($phrase)); 
             if ($pos > -1) break;
         }

         $startPos = 0; 
         if ($pos > $radius) { 
             $startPos = $pos - $radius; 
         } 

         $textLen = strlen($text); 

         $endPos = $pos + $phraseLen + $radius; 
         if ($endPos >= $textLen) { 
             $endPos = $textLen; 
         } 

         $excerpt = substr($text, $startPos, $endPos - $startPos); 
         if ($startPos != 0) { 
             $excerpt = substr_replace($excerpt, $ending, 0, $phraseLen); 
         } 

         if ($endPos != $textLen) { 
             $excerpt = substr_replace($excerpt, $ending, -$phraseLen); 
         } 

         return $excerpt; 
   } 

Highlight function

function highlight($c,$q){ 
$q=explode(' ',str_replace(array('','\\','+','*','?','[','^',']','$','(',')','{','}','=','!','<','>','|',':','#','-','_'),'',$q));
for($i=0;$i<sizeOf($q);$i++) 
    $c=preg_replace("/($q[$i])(?![^<]*>)/i","<span class=\"highlight\">\${1}</span>",$c);
return $c;}

Upvotes: 9

deceze
deceze

Reputation: 522125

function excerpt($text, $phrase, $radius = 100, $ending = "...") {
    $phraseLen = strlen($phrase);
    if ($radius < $phraseLen) {
        $radius = $phraseLen;
    }

    $pos = strpos(strtolower($text), strtolower($phrase));

    $startPos = 0;
    if ($pos > $radius) {
        $startPos = $pos - $radius;
    }

    $textLen = strlen($text);

    $endPos = $pos + $phraseLen + $radius;
    if ($endPos >= $textLen) {
        $endPos = $textLen;
    }

    $excerpt = substr($text, $startPos, $endPos - $startPos);
    if ($startPos != 0) {
        $excerpt = substr_replace($excerpt, $ending, 0, $phraseLen);
    }

    if ($endPos != $textLen) {
        $excerpt = substr_replace($excerpt, $ending, -$phraseLen);
    }

    return $excerpt;
}

Shamelessly stolen from the Cake TextHelper.

Upvotes: 4

Related Questions