Still nothing?
Let me try to explain one more time:
I’m writing a text filter, to convert certain words into links.
I have a MySQL table with each term and its corresponding words to link. This table has currently 30,126 rows, so every bit of optimization is necessary.
I have a function, now modified from before so I will show it below, which does the linking.
In order to reduce the number of terms to work through, I did a simple LIKE in the database to at least narrow down the terms. This has made it faster, but it is still pretty slow.
Here’s my function. Note that this is Drupal, so the database is queried with db_query:
function ce_execute_filter($text)
{
// If text is empty, return as-is
if (!$text) {
return $text;
}
// Split by paragraph
$lines = preg_split('/\
+/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
// Contains the parsed and linked text
$linked_text = '';
foreach ($lines as $line)
{
// If this fragment is only one or more newline characters,
// Add it to $linked_text and continue without parsing
if (preg_match('/^\
+$/', $line)) {
$linked_text .= $line;
continue;
}
// Select any terms that might be in this line
// Ordered by descending length of term,
// so that the longest terms get replaced first
$result = db_query('SELECT title, term FROM {catholic_encyclopedia_terms} ' .
"WHERE :text LIKE CONCAT('%', CONCAT(term, '%')) " .
'GROUP BY term ' .
'ORDER BY char_length(term) DESC',
array(
':text' => $line
))
->fetchAll();
// Array with lowercase term as key, title of entry as value
$terms = array();
// Array of the terms only in descending order of length
$ordered_terms = array();
foreach ($result as $r)
{
$terms[strtolower($r->term)] = $r->title;
$ordered_terms[] = preg_quote($r->term);
}
// If no terms were returned, add the line and continue without parsing.
if (empty($ordered_terms)) {
$linked_text .= $line;
continue;
}
// Do the replace
// Get the regexp by joining $ordered_terms with |
$line = preg_replace_callback('/\\b('.
implode('|', $ordered_terms) .
')\\b/i', function ($matches) use($terms)
{
if ($matches[1]) {
return "[cathenlink=" .
$terms[strtolower($matches[1])] . "]" .
$matches[1] . "[/cathenlink]";
}
},
$line);
$linked_text .= $line;
}
return $linked_text;
}
The cathenlink thing is a tag that will be replaced by an actual link later in the text.
OK, so this is getting closer, but still I want to figure out how to make it faster.