Schnellere Funktion mit ob_start(); ?

Freakz91

Grünschnabel
Hallo Leute,

ich zeige euch heute mal ein seoScript von mir das in dem CMS PHP-Fusion alle Links suchmaschinenoptimiert umschreibt.

Das Script wird mit ob_start(); aufgerufen...

PHP:
        function seotitle( $title )
	{
		$title = str_replace("ä", "ae", $title);
		$title = str_replace("Ä", "Ae", $title);
		$title = str_replace("ü", "ue", $title);
		$title = str_replace("Ü", "Ue", $title);
		$title = str_replace("ö", "oe", $title);
		$title = str_replace("Ö", "Oe", $title);
		$title = str_replace("ß", "ss", $title);
		$title = str_replace("€", "euro", $title);
		$title = str_replace("Re:-", "", $title);
		$title = str_replace("!", "", $title);
		$title = str_replace("$", "", $title);
		$title = str_replace("%", "", $title);
		$title = str_replace("&", "", $title);
		$title = str_replace("/", "", $title);
		$title = str_replace("(", "", $title);
		$title = str_replace(")", "", $title);
		$title = str_replace("=", "", $title);
		$title = str_replace("?", "", $title);
		$title = str_replace("´", "", $title);
		$title = str_replace("`", "", $title);
		$title = str_replace("{", "", $title);
		$title = str_replace("}", "", $title);
		$title = str_replace("[", "", $title);
		$title = str_replace("]", "", $title);
		$title = str_replace("+", "", $title);
		$title = str_replace("*", "", $title);
		$title = str_replace("~", "", $title);
		$title = str_replace("#", "", $title);
		$title = str_replace("'", "", $title);
		$title = str_replace(">", "", $title);
		$title = str_replace("<", "", $title);
		$title = str_replace("lt", "", $title);
		$title = str_replace("gt", "", $title);
		$title = str_replace("@", "", $title);
		$title = str_replace("|", "", $title);
		$title = str_replace("^", "", $title);
		$title = str_replace("°", "", $title);
		$title = str_replace(",", "", $title);
		$title = str_replace(";", "", $title);
		$title = str_replace(".", " ", $title);
		$title = str_replace(":", "", $title);
		$title = str_replace("_", "", $title);
		$title = str_replace("§", "", $title);
		$title = str_replace(" ", "-", $title);
		$title = str_replace("--", "-", $title);
		$title = str_replace("---", "-", $title);
		$title = str_replace("----", "-", $title);
		$title = strtolower($title);
		
		return $title;
	}


function seofusion($seo) 
{
	global $db_host, $db_user, $db_pass, $db_name, $locale, $settings;
	
	dbconnect($db_host, $db_user, $db_pass, $db_name);
	
	
if(!substr_count($_SERVER['REQUEST_URI'],"administration")){
		
if (isset($settings['seofusion']) && $settings['seofusion']==1) {


##viewpage.php



	function cpt($id) 
	{
		$title = dbarray(dbquery("SELECT page_title FROM ".DB_PREFIX."custom_pages WHERE page_id='$id'"));
		return (seotitle($title['page_title']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'viewpage\.php\?page_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'cp\\2_'.cpt('\\2').'.html\\3'", $seo);
	

	
##profile.php

	function gn($id) 
	{
		$title = dbarray(dbquery("SELECT group_name FROM ".DB_PREFIX."user_groups WHERE group_id='$id'"));
		return (seotitle($title['group_name']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'profile\.php\?group_id=([0-9]*?)(\'|")#sie',
	 "'\\1'.BASEDIR.'g\\2_'.gn('\\2').'.html\\3'", $seo);


	function un($id) 
	{
		$title = dbarray(dbquery("SELECT user_name FROM ".DB_PREFIX."users WHERE user_id='$id'"));
		return (seotitle($title['user_name']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'profile\.php\?lookup=([0-9]*?)(\'|")#sie',	
	"'\\1'.BASEDIR.'u\\2_'.un('\\2').'.html\\3'", $seo);


##news.php

	function ns($id) 
	{
		$title = dbarray(dbquery("SELECT news_subject FROM ".DB_PREFIX."news WHERE news_id='$id'"));
		return (seotitle($title['news_subject']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'news\.php\?readmore=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'n\\2_'.ns('\\2').'.html\\3'", $seo);


##news_cats.php

	function ncn($id) 
	{
		$title = dbarray(dbquery("SELECT news_cat_name FROM ".DB_PREFIX."news_cats WHERE news_cat_id='$id'"));
		return (seotitle($title['news_cat_name']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'news_cats\.php\?cat_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'nc\\2_'.ncn('\\2').'.html\\3'", $seo);
	
	
##articles.php

	function acn($id) 
	{
	   $title = dbarray(dbquery("SELECT article_cat_name FROM ".DB_PREFIX."article_cats WHERE article_cat_id='$id'"));
		return (seotitle($title['article_cat_name']));
	}	

	$seo = preg_replace('#(\'|")'.BASEDIR.'articles\.php\?cat_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'ac\\2_'.acn('\\2').'.html\\3'", $seo);
	
	
##readarticle.php

	function an($id) 
	{
		$title = dbarray(dbquery("SELECT article_subject FROM ".DB_PREFIX."articles WHERE article_id='$id'"));
		return (seotitle($title['article_subject']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'readarticle\.php\?article_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'a\\2_'.an('\\2').'.html\\3'", $seo);


##downloads.php

	function dcn($id) 
	{
	$title = dbarray(dbquery("SELECT download_cat_name FROM ".DB_PREFIX."download_cats WHERE download_cat_id='$id'"));
	return (seotitle($title['download_cat_name']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'downloads\.php\?cat_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'dc\\2_'.dcn('\\2').'.html\\3'", $seo);
	
	$seo = preg_replace('#downloads\.php\?cat_id=([0-9]*?)(&|&amp;)download_id=([0-9]*?)(\'|")#sie',
	"'dc\\1_'.dcn('\\1').'_d\\3.html\\4'", $seo);


##faq.php

	function qcn($id) 
	{
		$title = dbarray(dbquery("SELECT faq_cat_name FROM ".DB_PREFIX."faq_cats WHERE faq_cat_id='$id'"));
		return (seotitle($title['faq_cat_name']));
	}

	$seo = preg_replace('#(\'|")'.BASEDIR.'faq\.php\?cat_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'qc\\2_'.qcn('\\2').'.html\\3'", $seo);
	
	
##weblinks.php

	function lcn($id) 
	{
	   $title = dbarray(dbquery("SELECT weblink_cat_name FROM ".DB_PREFIX."weblink_cats WHERE weblink_cat_id='$id'"));
		return (seotitle($title['weblink_cat_name']));
	}
	

	$seo = preg_replace('#(\'|")'.BASEDIR.'weblinks\.php\?cat_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'lc\\2_'.lcn('\\2').'.html\\3'", $seo);
	
	$seo = preg_replace('#weblinks\.php\?cat_id=([0-9]*?)(&|&amp;)weblink_id=([0-9]*?)(\'|")#sie',
	"'lc\\1_'.lcn('\\1').'_l\\3.html\\4'", $seo);


##photogallery.php
	
	function pat($id) 
	{
		$title = dbarray(dbquery("SELECT album_title FROM ".DB_PREFIX."photo_albums WHERE album_id='$id'"));
		return (seotitle($title['album_title']));
	}
		
	$seo = preg_replace('#(\'|")'.BASEDIR.'photogallery\.php\?album_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'pa\\2_'.pat('\\2').'.html\\3'", $seo);
	
	
	function ppt($id) 
	{
		$title = dbarray(dbquery("SELECT photo_title FROM ".DB_PREFIX."photos WHERE photo_id='$id'"));
		return (seotitle($title['photo_title']));
	}
	
	$seo = preg_replace('#(\'|")'.BASEDIR.'photogallery\.php\?photo_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'p\\2_'.ppt('\\2').'.html\\3'", $seo);
	
	
##print.php 

	$seo = preg_replace('#(\'|")'.BASEDIR.'print\.php\?type=N&amp;item_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'print.php?type=N&item_id=\\2&'.ns('\\2').'\\3'", $seo);

	$seo = preg_replace('#(\'|")'.BASEDIR.'print\.php\?type=A&amp;item_id=([0-9]*?)(\'|")#sie',
	"'\\1'.BASEDIR.'print.php?type=A&item_id=\\2&'.an('\\2').'\\3'", $seo);
	
	
	
##viewforum.php

	function fn($id) 
	{
		$title = dbarray(dbquery("SELECT forum_name FROM ".DB_PREFIX."forums WHERE forum_id='$id'"));
		return (seotitle($title['forum_name']));
	}

	$seo = preg_replace('#viewforum\.php\?forum_id=([0-9]*?)(\'|")#sie',
	"'\\1_'.fn('\\1').'.html\\2'", $seo);
	
	
##viewthread.php

	function ts($id) 
	{
		$title = dbarray(dbquery("SELECT thread_subject FROM ".DB_PREFIX."threads WHERE thread_id='$id'"));
		return (seotitle($title['thread_subject']));
	}

	$seo = preg_replace('#viewthread\.php\?forum_id=([0-9]*?)(&|&amp;)thread_id=([0-9]*?)(&|&amp;)pid=([0-9]*?)\#post_([0-9]*?)(\'|")#sie',
	"'t\\3_'.ts('\\3').'_f\\1_p\\5.html#post_\\6\\7'", $seo);

	$seo = preg_replace('#viewthread\.php\?forum_id=([0-9]*?)(&|&amp;)thread_id=([0-9]*?)(\'|")#sie',
	"'t\\3_'.ts('\\3').'_f\\1.html\\4'", $seo);
 
 	$seo = preg_replace('#viewthread\.php\?forum_id=([0-9]*?)(&|&amp;)thread_id=([0-9]*?)(&|&amp;)rowstart=([0-9]*?)(\'|")#sie',
	"'t\\3_'.ts('\\3').'_f\\1_r\\5.html\\6'", $seo);
	
	
##navigations_links

	$seo = preg_replace("#contact.php#si",
 	$locale['SEO60'].".html", $seo);
	
	$seo = preg_replace("#register.php#si",
 	$locale['SEO61'].".html", $seo);
					
	$seo = preg_replace("#edit_profile.php#si",
 	$locale['SEO62'].".html", $seo);
	
	$seo = preg_replace("#articles.php#si",
 	$locale['SEO63'].".html", $seo);
	
	$seo = preg_replace("#(\"|')".BASEDIR."downloads\.php(\"|')#si",
	BASEDIR.$locale['SEO64'].".html", $seo);
	
	$seo = preg_replace("#(\"|')".BASEDIR."search\.php(\"|')#si",
	BASEDIR.$locale['SEO71'].".html", $seo);
	
	$seo = preg_replace("#faq.php#si",
 	$locale['SEO65'].".html", $seo);
					
	$seo = preg_replace("#weblinks.php#si",
	$locale['SEO66'].".html", $seo);
	
	$seo = preg_replace("#photogallery.php#si",
 	$locale['SEO67'].".html", $seo);
	
	$seo = preg_replace("#news_cats.php#si",
 	$locale['SEO68'].".html", $seo);
	
	$seo = preg_replace("#news.php#si",
 	$locale['SEO19'].".html", $seo);
	
	$seo = preg_replace("#lostpassword.php#si",
	$locale['SEO69'].".html", $seo);
	
	$seo = preg_replace("#sitemap.php#si",
 	$locale['SEO70'].".html", $seo);
	
	$seo = preg_replace("#members.php#si",
 	$locale['SEO72'].".html", $seo);
	
	$seo = preg_replace("#messages.php#si",
 	$locale['SEO79'].".html", $seo);
	
	$seo = preg_replace("#submit\.php\?stype=l#si",
 	$locale['SEO73']."_".$locale['SEO77'].".html", $seo);
	
	$seo = preg_replace("#submit\.php\?stype=n#si",
 	$locale['SEO73']."_".$locale['SEO75'].".html", $seo);
	
	$seo = preg_replace("#submit\.php\?stype=a#si",
 	$locale['SEO73']."_".$locale['SEO74'].".html", $seo);
	
	$seo = preg_replace("#submit\.php\?stype=p#si",
	$locale['SEO73']."_".$locale['SEO76'].".html", $seo);

}
mysql_close();

}
	
	return $seo;
	
}

		ob_start("seofusion");


Nun meine Frage:
Kann man das Script irgendwie schneller machen? Es funktioniert zwar sehr gut aber bei sehr großen Seiten dauert das laden dann schon etwas länger...

Mfg Freakz
 
Die erste Funktion (seotitle()) kann durchaus schneller gemacht werden, in dem man nur einmal [phpf]str_replace[/phpf] aufruft und als Parameter eben einen Array benutzt.

Bei den anderen Funktionen könnte ich mir vorstellen, dass man statt X verschiedenen Funktionen zum Auslesen der Datenbankinhalte nur eine benutzt, die eben einen Array zurückgibt, mit allem was man braucht... Aber das ist auch eine Frage der Möglichkeiten, ich hab es jetzt nur mal eben überflogen. Hängt auch davon ab, wie oft die Funktion benutzt wird.
 
Das Problem ist, dass mit jedem Aufruf von preg_replace() die gesamte Zeichenkette durchsucht wird (was in deinem Fall mindestens 39 mal ist!). Und bei jeder gefundenen Übereinstimmung wird der Ersatzausdruck ausgewertet, die entsprechende Funktion aufgerufen, für den einen Wert eine Datenbankabfrage gemacht und dieser nochmals durch eine Funktion geschickt wird.

Das ist äußerst ineffizient! Besser wäre es, wenn du erst sämtliche Daten mit nur einem regulären Ausdruck sammelst (entspricht einem nur einmaligen Durchsuchen), die Daten gruppierst und für jede Datengruppe nur eine Datenbankabfrage machst.

Das Ganze könnte dann beispielsweise wie folgt aufgebaut sein:
PHP:
$parts = preg_split('#((\'|")'.BASEDIR.'[^?]+\?[a-z_]+=[0-9]+$2)#', $str, 0, PREG_SPLIT_DELIM_CAPTURE);
$groups = array();
$groupSpecificPatterns = array(
	'viewpage.php' => '([a-z_]+)=([0-9]+)\\1',
	// …
);
$groupSpecificReplacement = array(
	// %s steht für den Rückgabewert der jeweiligen Funktion
	'viewpage.php' => '\\1'.BASEDIR.'cp\\4_%s.html\\1',
	// …
);
$matches = array();
foreach ($parts as $key => $part) {
	// prüfe ob Teil eine URL ist und zu welcher Gruppe es gehört
	if (!preg_match('#^(?:\'|")'.BASEDIR.'([^?\'"]+)#', $part, $match)) {
		continue;
	}
	// prüfe ob Gruppe bekannt ist und Regeln dafür existieren
	if (!isset($groupSpecificPatterns[$match[1]]) || !preg_match('#^(\'|")'.BASEDIR.'([^?\'"]+)\?'.$groupSpecificPatterns[$match[1]].'#', $part, $match)) {
		continue;
	}
	// sammele IDs in Gruppen zusammengefasst
	$groups[$match[2]][$key] = $match[4];
	// sammele Treffer, um diese später ersetzen zu können
	$matches[$match[2]][$key] = $match[0];
}
// gibt die Funktionen der Gruppen an
$functions = array(
	'viewpage.php' => 'cpt',
	// …
);
// Beispiel für eine Gruppenfunktion
function cpt($ids)
{
	$resultset = dbarray(dbquery("SELECT page_id, page_title FROM ".DB_PREFIX."custom_pages WHERE page_id IN ('".implode(', ', $ids)."'"));
	$retVal = array();
	foreach ($resultset as $result) {
		$retVal[$result['page_id']] = seotitle($result['page_title']);
	}
	return $retVal;
}
// führe die Funktionen gruppenweise aus
foreach ($groups as $key => $values) {
	$ids = array();
	foreach ($values as $value) {
		$ids[] = $value[1];
	}
	$groups[$key] = $functions[$key]($ids);
}
$buffer = '';
// ersetze die Werte
$replacement = array();
foreach ($groups as $groupId => $values) {
	if (!isset($groupSpecificReplacement[$groupId])) {
		continue;
	}
	foreach ($values as $key => $value) {
		$replacement[$key] = sprintf(preg_replace('#^(\'|")'.BASEDIR.preg_quote($groupId).'?'.$groupSpecificPatterns[$groupId].'#', $groupSpecificReplacement[$groupId], $matches[$groupId][$key]), $groups[$groupId][$key]);
	}
}
// zusammenführen der Teile
$parts = $replacement + $parts; 
ksort($parts);
echo implode('', $parts);
Sieht schrecklich kompliziert aus und funktioniert wahrscheinlich auch nicht.
 
Ich verstehe was du meinst und ich denke das könnte tatsächlich so viel schneller gehen, nur steige ich durch deine Funktion noch nicht so ganz durch und die funktioniert auch nicht wirklich....

Ich habe erstmal mal die Funktion seotitle(); verbessert:
PHP:
    function seotitle( $title )
    {
        $search = array("ä", "Ä", "ü", "Ü", "ö", "Ö", "ß", "€", "RE:-");
        $replace = array("ae", "Ae", "ue", "Ue", "oe", "Oe", "ss", "euro", "" );
        $title = str_replace($search, $replace, $title);;
        $title = preg_replace("/[^\d\w]+/", "-", $title);
        $title = trim($title, "-");
        $title = strtolower($title);
        
        return $title;
    }

hat sonst noch jemand Ideen wie ich das schneller machen könnte?

Mfg Freakz
 
Das von mir genannte war auch nur ein spekulatives Beispiel, das durch das Gruppieren auch recht komplex wird. Wenn du das allerdings weglässt, wird es schon wesentlich einfacher und verständlicher:
PHP:
$parts = preg_split('#((\'|")'.BASEDIR.'[^?]+\?[a-z_]+=[0-9]+\\2)#', $str, 0, PREG_SPLIT_DELIM_CAPTURE);
$rules = array(
	'viewpage.php' => array(
		'#^(\'|")'.BASEDIR.'([^?\'"]+)\?([a-z_]+)=([0-9]+)\\1#',
		'\\1'.BASEDIR.'cp\\4_%s.html\\1',
		'cpt',
	),
	// …
);
$matches = array();
foreach ($parts as $key => $part) {
	// prüfe ob Teil eine URL ist und zu welcher Gruppe es gehört
	if (!preg_match('#^(?:\'|")'.BASEDIR.'([^?\'"]+)#', $part, $match)) {
		continue;
	}
	$id = $match[1];
	// prüfe ob Gruppe bekannt ist und Regeln dafür existieren
	if (!isset($rules[$id]) || !preg_match($rules[$id][0], $part, $match)) {
		continue;
	}
	$parts[$key] = preg_replace($rules[$id][0], sprintf($rules[$id][1], $rules[$id][2]($match[4])), $match[0]);
}
$str = implode('', $parts);
 
Zurück