12. januar 2012 - 00:02
Der er
14 kommentarer
Optimering af script
Iforbindelse med en webshop har jeg et script der eksportere data til diverse prissøgninger på nettet, men problemet er at det indtil nu har virket fint.
Men efter at have tilføjet flere produkter så den nu skal hente +6000 produkter ligger den serveren ned eller får timeout.
Timeout kan ikke sætte længere op..
Er det muligt at optimere scriptet...
Her er scriptet
<?php
include(dirname(__FILE__).'/config/config.inc.php');
require_once(dirname(__FILE__).'/init.php');
$max_execution_time = 60 ;
$confPasswd = '';
$tags = array(
'name' => 'produktnavn',
'ean13' => 'ean13',
'ISBN' => 'ISBN',
'url' => 'link',
'lager' => 'LagerNiveau',
'imageUrl' => 'billedeUrl',
'price_inc' => 'pris',
'description_short' => 'produktbeskrivelse',
// 'description' => 'langbeskrivelse',
'id_product' => 'databaseid',
'reference' => 'interntvarenummer',
'categoryName' => 'category',
'subCategoryName' => 'subCategory',
'shipping_cost' => 'fragt',
'leveringstid' => 'leveringstid',
'manufacturerName' => 'producent',
'supplier_reference' => 'produktID ',
'lagerstatus' => 'PaaLager ',
);
function my_strip_tags($t)
{
$t = preg_replace('/</',' <',$t);
$t = preg_replace('/>/','> ',$t);
$t = preg_replace('/[\n\r\t]/',' ',$t);
$t = preg_replace('/ /',' ',$t);
return strip_tags($t);
}
function my_number_format($t)
{
return number_format($t, 2, ',', '.');
}
function print_field($k, $v)
{
global $tags;
if (isset($tags[$k])) {
$k = $tags[$k];
$v = htmlspecialchars($v, ENT_NOQUOTES, "UTF-8");
print " <$k>$v</$k>\n";
}
}
header("Content-Type:text/xml; charset=utf-8");
print '<?xml version="1.0" encoding="UTF-8"?>'."\n";
print "<products>\n";
$configuration = Configuration::getMultiple(array(
'PS_LANG_DEFAULT',
'PS_SHIPPING_FREE_PRICE',
'PS_SHIPPING_HANDLING',
'PS_SHIPPING_METHOD',
'PS_SHIPPING_FREE_WEIGHT',
'PS_CARRIER_DEFAULT'));
$id_lang = intval($configuration['PS_LANG_DEFAULT']);
$id_zone = intval($defaultCountry->id_zone);
$link = new Link();
$id_carrier = $configuration['PS_CARRIER_DEFAULT'];
$carrier = new Carrier(intval($id_carrier));
$carrierTax = 0;
if ($carrier->id_tax) {
$tax = new Tax(intval($carrier->id_tax));
if (Validate::isLoadedObject($tax) AND Tax::zoneHasTax(intval($tax->id), intval($id_zone)) AND !Tax::excludeTaxeOption())
$carrierTax = $tax->rate;
}
$passwd = Tools::getValue('passwd');
$categories = Category::getCategories($id_lang, true, false);
$manufacturers = Manufacturer::getManufacturers(false, $id_lang);
if ($passwd == $confPasswd) {
$products = Product::getProducts($id_lang, 0, 0, 'price', 'ASC', false, true);
}
else {
$products = array();
}
$manMap =array();
foreach ($manufacturers as $manufacturer) {
$manMap[$manufacturer['id_manufacturer']] = $manufacturer;
}
$catMap =array();
foreach ($categories as $category) {
$catMap[$category['id_category']] = $category;
}
foreach ($products as $product) {
$prodObj = new Product($product['id_product'], false, $id_lang);
$product['url'] = $link->getProductLink($prodObj);
$cover = Product::getCover($product['id_product']);
$product['imageUrl'] = _PS_BASE_URL_.$link->getImageLink($prodObj->link_rewrite, $product['id_product'].'-'.$cover['id_image'], 'large');
if (intval($configuration['PS_SHIPPING_METHOD']))
$shipping_cost = $carrier->getDeliveryPriceByWeight($product['weight'], $id_zone);
else
$shipping_cost = $carrier->getDeliveryPriceByPrice($product['price'], $id_zone);
$shipping_cost *= 1 + ($carrierTax / 100);
$shipping_cost += floatval($configuration['PS_SHIPPING_HANDLING']);
$product['shipping_cost'] = $shipping_cost;
$product['price_exc'] = my_number_format($prodObj->getPrice(false));
$product['price_inc'] = my_number_format($prodObj->getPrice(true));
// $price = $product['price'] * (1 + $product ['tax_rate'] / 100 );
// $product['price_inc'] = number_format($price, 2, ',', '.');
$product['manufacturerName'] = $manMap[$product['id_manufacturer']]['name'];
$product['description_short'] = my_strip_tags($product['description_short']);
if ($product ['quantity']==0)
$product['lagerstatus'] = 'Nej';
else
$product['lagerstatus'] = 'Ja';
$product['lager'] = $product['quantity'];
if ($product ['quantity']==0)
$product['leveringstid'] = ($product['available_later']);
else
$product['leveringstid'] = '1 - 3 dage';
//print " <product>\n";
$product_num++;
echo '<product place="'.$product_num.'">'."\n";
foreach ($product as $k => $v) {
print_field($k, $v);
}
$catList = Product::getIndexedCategories($product['id_product']);
foreach ($catList as $cat) {
$catNames = array();
$catId = $cat['id_category'];
while ($catId && $catId != 1) {
array_unshift($catNames, trim($catMap[$catId]['name']));
$catId = $catMap[$catId]['id_parent'];
}
print_field('categoryName', implode(' | ', $catNames));
}
print " </product>\n";
}
print "</products>\n";
?>
12. januar 2012 - 12:07
#1
Ja. Du kan minimere antallet af funktion kald til at begynde med:
function my_number_format($t)
{
return number_format($t, 2, ',', '.');
}
du kunne så bare skrive:
number_format($t, 2, ',', '.');
hvor du har:
my_number_format($t);
du har to if sætninger:
if ($product ['quantity']==0)
$product['lagerstatus'] = 'Nej';
else
$product['lagerstatus'] = 'Ja';
$product['lager'] = $product['quantity'];
if ($product ['quantity']==0)
$product['leveringstid'] = ($product['available_later']);
else
$product['leveringstid'] = '1 - 3 dage';
Såvidt jeg kan se tester de præcis det samme, så de kan slås sammen til:
if ($product ['quantity']==0){
$product['lagerstatus'] = 'Nej';
$product['leveringstid'] = ($product['available_later']);
}else{
$product['lagerstatus'] = 'Ja';
$product['leveringstid'] = '1 - 3 dage';
}
$product['lager'] = $product['quantity'];
du har:
1 + ($carrierTax / 100);
Det er såvidt jeg kan se konstant i forløkken så kan udregnes før løkken. (Fortolkeren laver muligvis selv denne forbedring.)
Du stripper tags. Jeg ville foreslå at du gjorde når du indsatte beskrivelsen, bare have 2 kolonner i databasen et med og et uden tags. (Antager at beskrivelserne er storset konstante efter de er blevet skrevet.)
De her kan skrives som en ting:
$shipping_cost *= 1 + ($carrierTax / 100);
$shipping_cost += floatval($configuration['PS_SHIPPING_HANDLING']);
$product['shipping_cost'] = $shipping_cost;
Det her er det samme:
$product['shipping_cost'] = $shipping_cost * (1 + ($carrierTax / 100)) + floatval($configuration['PS_SHIPPING_HANDLING']);
Din nederste med printning af kategorier ser en anelse mystisk ud, medmindre $catlist faktisk er en liste af lister af kategorier, så er den inderste while løkke vel næppe relevant, er bare en if sætning.
I stedet for at opbygge dit associative product array, kunne du bare bruge direkte variabler og have flere print_field linier. (Ved ikke om det er en forbedring, men kunne forestille mig at det ikke er helt gratis at opbygge og slå op i sådan et.)
12. januar 2012 - 16:24
#2
<ole>
Tværtimod bruger du arrays for lidt! =)
At skrive til dokumentet er noget, der tager tid. Derfor bør du tilstræbe at udskrive én gang - f.eks. ved at implodere et array. Og du bør ikke være bange for at bruge arrays - de er generelt lynhurtige at arbejde med.
Hvis du ændrede din funktion
print_field, så den ikke skriver ud, men nøjes med at formatere de enkelte tags og fylde dem i et array. Derefter kan du så skrive hele array'et ud i ét hug:
$formatted_tags = array();
function print_field($k, $v, $tags)
{
if (isset($tags[$k])) {
$k = $tags[$k];
$v = htmlspecialchars($v, ENT_NOQUOTES, "UTF-8");
$formatted_tags = " <$k>$v</$k>";
}
}
// - og længere nede
foreach ($product as $k => $v) {
print_field($k, $v, $tags);
}
print implode("\n", $formatted_tags);
Det vil forbedre scriptets performance en hel del - og du vil sikkert selv kunne ændre til samme fremgangsmåde flere steder.
I funktionen
my_strip_tags bruger du
preg_replace, som fungerer forholdsvis langsomt. Kik i stedet på
strtr her. Den er beregnet til at oversætte ord/tegn i en streng. Brug den med to arrays.
Jeg har ikke kikket koden efter i enkeltheder, men disse to ting sprang i hvertfald i øjnene =)
/mvh
</bole>
12. januar 2012 - 16:28
#3
- og det fik jeg skrevet lidt for hurtigt!
function print_field($k, $v, $tags)
{
$formatted_tags = array();
if (isset($tags[$k])) {
$k = $tags[$k];
$v = htmlspecialchars($v, ENT_NOQUOTES, "UTF-8");
$formatted_tags[] = " <$k>$v</$k>";
}
return $formatted_tags;
}
// - og længere nede
foreach ($product as $k => $v) {
$formatted_tags = print_field($k, $v, $tags);
}
print implode("\n", $formatted_tags);
Læg i øvrigt mærke til, at jeg bevidst begrænser brugen af globale variabler mest muligt. I stedet sender jeg dem med til funktionen som argumenter - og returnerer dem igen.
12. januar 2012 - 17:19
#4
Tak for svarene indtil videre prøver at kigge lidt på det.
Det som script laver er en prisfil der bla hentes af pricerunner,og udtrækket ser/skal altid se således ud.:
<product place="4418">
<databaseid>7371</databaseid>
<ean13>7611990190607</ean13>
<interntvarenummer>344117320</interntvarenummer>
<produktID>21.18.1753</produktID>
<produktbeskrivelse> IEEE 802.11n, IEEE 802.11g, IEEE 802.11b Frekvens: 2,4 - 2,4835 GHz Plug & Play Support WPS (Wifi beskyttet setup) Support QoS-WMM,WMM-PS </produktbeskrivelse>
<produktnavn>Trådløst netværk - USB2.0 antenne - 150 Mbit/s -</produktnavn>
<link>
http://www.mbmdata.dk/netvarksprodukter-netkort/7371-trdlst-netvrk---usb20-antenne---150-mbits----7611990190607.html</link><billedeUrl>
http://www.mbmdata.dk/7371-7369-large/trdlst-netvrk---usb20-antenne---150-mbits---.jpg</billedeUrl><fragt>39</fragt>
<pris>230,16</pris>
<producent>ROLINE</producent>
<PaaLager>Ja</PaaLager>
<leveringstid>1 - 3 dage</leveringstid>
<LagerNiveau>6</LagerNiveau>
<category>Netværksprodukter | Netkort</category>
</product>
Der hentes lige p.t omkring 6100 produkter så det tager lidt tid, der ville jeg gerne optimere scriptet for at forkorte tiden og forbedre performance.
12. januar 2012 - 17:21
#5
function my_number_format($t)
{
return number_format($t, 2, ',', '.');
}
du kunne så bare skrive:
number_format($t, 2, ',', '.');
hvor du har:
my_number_format($t);
Den forstod jeg ikke helt...
Skal jeg fjerne
function my_number_format($t)
{
return number_format($t, 2, ',', '.');
}
eller hvordan skal det forstået