ugrás a tartalomhoz

Maximum execution time of 30 seconds exceeded hiba

toldigabor · 2014. Jún. 20. (P), 20.58
Van egy ilyen forráskódrészletem, amelyben a keresés során talált szövegekben az összes keresett szó összes előfordulását kiemeli a mark html tag-gel:

$j=1;
mysql_data_seek($lekerdezes,0);
while ($rekord=mysql_fetch_array($lekerdezes))
 {
  $szoveg=$rekord['szoveg'];
  for ($k=0; $k<count($keresendok); $k++)
   {
    $keresendo_hossz=mb_strlen($keresendok[$k],'UTF-8');
	$alap_poz=0;
	while (mb_strpos(mb_strtolower($szoveg,'UTF-8'),mb_strtolower($keresendok[$k],'UTF-8'),$alap_poz,'UTF-8')!==false)
	 {
	  $szoveg_hossz=mb_strlen($szoveg,'UTF-8');
	  $kezdo_poz=mb_strpos(mb_strtolower($szoveg,'UTF-8'),mb_strtolower($keresendok[$k],'UTF-8'),$alap_poz,'UTF-8');
	  $veg_poz=$kezdo_poz+$keresendo_hossz;
	  $szoveg=mb_substr($szoveg,0,$kezdo_poz,'UTF-8') . "<mark>" . mb_substr($szoveg,$kezdo_poz,$keresendo_hossz,'UTF-8') . "</mark>" . mb_substr($szoveg,$veg_poz,$szoveg_hossz,'UTF-8');
	  $alap_poz=$veg_poz+1;
	 }
   }
  echo "     <p><strong>" . $j++ . ".</strong> " . $szoveg . " <em><a href='valami_link.php'>" . $valami . "</a></em></p>\n";
 }
De a fenti hibát produkálja. És az a gáz, hogy ha a mark helyett em-et írok már jó, de ha egy 3 karakteres html tag-gel emelem ki (mondjuk próba képpen a sup) akkor már jó, sőt ha a nyitó vagy a záró markból csak egyetlen karaktert is kiemelek, akkor sem ír már hibaüzenetet. Pont azzal az egyetlen karakterrel lesz tele a hócipője.
 
1

Próbálhatnál kevesebb

Vilmos · 2014. Jún. 20. (P), 22.03
Próbálhatnál kevesebb konvertálást végezni.
Például, az 5. sorban a "szoveg" változót rögtön lehetne alakítani, nem minden egyes előfordulási ponton. A "keresendo" tömbről ugyanez elmondható, a 8. sorban használod, a "dataseek" előtt már előkészített állapotban lehetne.
4

+1

numen · 2014. Jún. 21. (Szo), 12.41
És valóban:
– a szoveg_hossz-t elég a legkülső ciklusban kiszámolni,
– ugyanez igaz az mb_strtolower(szoveg)-re

– Én lehet, hogy megpróbálnék egy mb_ereg_replace -et case insensitive-en használni (az mb_eregi_replace-nál pont szerepel a problémád a hozzászólások közt)

– Csúnya megoldás, ha tényleg másik taget használsz, és CSS-re bízod a maradékot :P
2

str_replace

bonga · 2014. Jún. 20. (P), 23.06
Mi lenne, ha az egész keresés és cserét a php-ra bíznád? Úgy biztosan gyorsabb lenne és talán nem futnál bele a hosszú feldolgozási időkorlátba.
Arra gondolok, hogy a $keresendok tömbből először építeni kellene mondjuk egy $kiemelesek tömböt, amely a keresendő szavakat az elvárt alakban (<mark>szo</mark>) tartalmazza, és utána egy egyszerű str_replace($keresendok, $kiemelesek, $szoveg) függvényhívással megoldhatnád az egészet:

$kiemelesek = array();
for ($i=0; $i<count($keresendok); $i++)
  $kiemelesek[$i] = '<mark>'.$keresendok[$i].'</mark>';

$j=1;
mysql_data_seek($lekerdezes, 0);
while ($rekord = mysql_fetch_array($lekerdezes))
{
  $szoveg = str_replace($keresendok, $kiemelesek, $rekord['szoveg']);
  echo "     <p><strong>" . $j++ . ".</strong> " . $szoveg . " <em><a href='valami_link.php'>" . $valami . "</a></em></p>\n";
}
3

Kis- és nagybetűk

toldigabor · 2014. Jún. 21. (Szo), 05.47
Ez a kis- és nagybetűk miatt problémás. Ha a keresés mondjuk nagykezdőbetűvel történt, akkor a szövegek előfordulásaiban így át fogja írni ott is nagykezdőbetűsre, ahol kiskezdőbetűs előfordulás volt.
5

preg_replace

bonga · 2014. Jún. 22. (V), 16.42
Azt hiszem, hogy ez így ebben a formában nem igaz, mert az srt_replace case sensitive, vagyis pont, hogy nem fogja átírni ott is nagy kezdőbetűsre, ahol kis kezdőbetűs előfordulás volt.
Viszont az igaz, hogy a case sensitiveness miatt nem is fogja kiemelni a csak kis-nagybetűből fakadó eltéréseket.

De akkor javaslok egy még egyszerűbb megoldást preg_replace-el, mert ez tutin kezeli az utf8-at is és a case eltérést is bármely karakteren:

$j=1;  
mysql_data_seek($lekerdezes, 0);  
while ($rekord = mysql_fetch_array($lekerdezes))  
{  
  $szoveg = $rekord['szoveg'];
  foreach($keresendok as $kiemelendo)
  {
    $szoveg = preg_replace('/('.$kiemelendo.')/iu', '<mark>${1}</mark>', $szoveg);
  }
  echo "     <p><strong>" . $j++ . ".</strong> " . $szoveg . " <em><a href='valami_link.php'>" . $valami . "</a></em></p>\n";  
}
Szerk.:
Ez a megoldás egészen addig jó lesz, amíg az biztos, hogy a $keresendok tömb biztosan csak szavakat/szórészleteket tartalmaz. Arra figyelni kell, hogy amennyiben regexp-pattern kerül bele, akkor az boríthatja a keresést/cserét.
6

preg_quote

complex857 · 2014. Jún. 22. (V), 17.03
A belső loop elvileg kiváltható ha a regexp pattern eleve tartalmaz minden kiemelendő kifejezést (magát a pattern-t elvileg elég egyszer a db sorok loopján kívül előállítani), valahogy így:

$pattern = join('|', array_map('preg_quote', $keresendok));
while ($rekord = mysql_fetch_array($lekerdezes))
{
    $szoveg = preg_replace('/('.$pattern.')/iu', '<mark>$1</mark>', $rekord['szoveg']);
    echo "...";
}

preg_quote
a keresendő mintákban előforduló speciális jelentésű dolgokat is biztonságosan fogyaszthatóvá teszi későbbi mintaillesztésre.