2017-07-26 35 views
0

我解析XML文件,如果存在,我想INSERT的XML元素节点,如果ID不存在,或者UPDATE记录......解析XML并插入到数据库是否存在,否则UPDATE

这是到目前为止我的代码:

<?php 
header('Content-type: text/html; charset=UTF-8') ; 
//connection to DB here.. 
//.... .. .. .. .. 


// Create connection 
$conn = new mysqli($servername, $dbuser, $password, $dbname,3306); 
// Check connection 
if ($conn->connect_error) { 
    die("Connection failed: " . $conn->connect_error); 
} 
// Change character set to utf8 
$conn->set_charset("utf8"); 
date_default_timezone_set('Europe/Athens'); 

$date_modified = strtotime("now"); 
$business_id = 54; 
$xml_link = "https://www.mydomain.gr/test.xml"; 
$xml_link = $conn->real_escape_string($xml_link); 
$xml_link = trim(stripslashes($xml_link)); 

在这里,我更新记录 “DATE_MODIFIED” ..

$update_business_xml = $conn->query('UPDATE business_xml SET date_modified="' . $date_modified . '" WHERE business_id=54'); 

现在,在这部分代码,我得到的产品的所有ID,并把它们放在一个数组

$count_errors = 0; 
//query to find products ids 
$query_ids = $conn->query('SELECT pid FROM products WHERE business_id=54'); 
$rows_ids = mysqli_num_rows($query_ids); 
$count_id = 0; 
if($rows_ids > 0) { 
    while($exe_ids = mysqli_fetch_object($query_ids)) { 
     $arr_ids[$count_id] = $exe_ids->pid; 
     $count_id++; 
    } 
} 

$reader = new XMLReader(); 
$reader->open($xml_link);   
while($reader->read()) { 
    if($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'product') { 
     $product = new SimpleXMLElement($reader->readOuterXml()); 

     $pid = $product->id; 
     $name = $product->name; 
     $name = mb_strtolower($name,'UTF-8'); 
     $mpn = $product->mpn; 
     $ean = $product->ean; 
     $sku = $product->sku; 
     $link = $product->link; 
     $price = $product->price; 
     $category_id = $product->category->attributes(); 
     $category_path = $product->category; 
     $category_path = mb_strtolower($category_path,'UTF-8'); 
     $image = $product->image; 
     $availability = $product->availability; 
     $size = $product->size; 
     $size = mb_strtolower($size,'UTF-8'); 
     $color = $product->color; 
     $color = mb_strtolower($color,'UTF-8'); 
     $weight = $product->weight; 
     $description = $product->description; 
     $manufacturer = $product->manufacturer; 
     $manufacturer = trim($manufacturer); 
     $instock = "Y"; 
     $product_image = $image; 
     $check_product_url = $link; 

     $exist_pids = 0; 
     if(!empty($pid) || !empty($image) || !empty($price) || !empty($name) || !empty($link) || !empty($manufacturer)) { 
      if($category_id == 613 || $category_id == 604 || $category_id == 635) { 

我有一些类别的XML,我不想让他们在我的数据库里面,所以我在这里我正在获取该类别的属性,并检查这个产品是否是其中的一个,只需将该记录的状态更新到我的数据库。

   $update_business_xml = $conn->query('UPDATE products SET status=0 WHERE business_id="' . $business_id . '" AND pid= "' . $pid . '"'); 
       $count_errors++; 
      } 
      else { 
       $status = 1; 
       $date = date('d-m-Y H:i:s'); //when insert a pr 
       $date_modified = strtotime("now"); //when modify a pr 
       $insert_business_xml = $conn->query('INSERT INTO products (business_id,pid,name,category,product_link,price,size,color,weight,description,manufacturer,mpn,ean,image,sku,instock,availability,status,date_added) VALUES("'.$business_id.'", 
       "' . mysqli_real_escape_string($conn,stripslashes($pid)) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes($name)) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($category_path))) . '", 
       "' . $check_product_url . '", 
       "' . mysqli_real_escape_string($conn,stripslashes($price)) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($size)))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($color)))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($weight))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($description))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($manufacturer)))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($mpn))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($ean))) . '", 
       "' . $product_image . '", 
       "' . mysqli_real_escape_string($conn,stripslashes(trim($sku))) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes($instock)) . '", 
       "' . mysqli_real_escape_string($conn,stripslashes($availability)) . '", 
       "' . $status . '", "' . $date . '") ON DUPLICATE KEY UPDATE 
       "business_id='.$business_id.'", 
       "pid=' . mysqli_real_escape_string($conn,stripslashes($pid)) . '", 
       "name=' . mysqli_real_escape_string($conn,stripslashes($name)) . '", 
       "category=' . mysqli_real_escape_string($conn,stripslashes(trim($category_path))) . '", 
       "product_link=' . $check_product_url . '", 
       "price=' . mysqli_real_escape_string($conn,stripslashes($price)) . '", 
       "size=' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($size)))) . '", 
       "color=' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($color)))) . '", 
       "weight=' . mysqli_real_escape_string($conn,stripslashes(trim($weight))) . '", 
       "description=' . mysqli_real_escape_string($conn,stripslashes(trim($description))) . '", 
       "manufacturer=' . mysqli_real_escape_string($conn,stripslashes(trim(strtolower($manufacturer)))) . '", 
       "mpn=' . mysqli_real_escape_string($conn,stripslashes(trim($mpn))) . '", 
       "ean=' . mysqli_real_escape_string($conn,stripslashes(trim($ean))) . '", 
       "image=' . $product_image . '", 
       "sku=' . mysqli_real_escape_string($conn,stripslashes(trim($sku))) . '", 
       "instock=' . mysqli_real_escape_string($conn,stripslashes($instock)) . '", 
       "availability=' . mysqli_real_escape_string($conn,stripslashes($availability)) . '", 
       "status=' . $status . '", 
       "date_modified=' . $date_modified . '"'); 

在我使用的INSERT INTO上面的代码......对重复密钥更新,以检查是否存在的ID,只需更新此记录。如果该ID不存在的所有值,插入此一个.. 在我的代码beggining因为我告诉,我得到了所有的ID阵列中的,所以我在这里消除已发现的ID ..

   //erase from arr_ids 
       if(($key = array_search($pid, $arr_ids)) !== false) { 
        unset($arr_ids[$key]); 
       } 
      } 
     } 
     else { 
      $update_business_xml = $conn->query('UPDATE products SET status=0, date_modified="' . $date_modified . '" WHERE business_id="' . $business_id . '" AND pid= "' . $pid . '"'); 
      $count_errors++; 
     } 
    } //reader nodeType 
} //end while loop 
$reader->close(); 

最后但并非最不重要的,在这里,我也更新了所有其余的ID已经留在阵列内的记录..这意味着这些ID,不存在或没有在XML内部列出更多。

foreach($arr_ids as $id) { 
    $update_business_xml = $conn->query('UPDATE products SET status=0 WHERE business_id="' . $business_id . '" AND pid= "' . $id . '"'); 
} 

最后,我才能看到多少错误有一个简单的信息。通过说错误,我指的是XML的多条记录怎么了空元素(名称,价格,链接,图像.. ..等),只是让回声..

//var_dump($arr_ids); 
$insert_messages = "Your XML file has been updated successfully! We found <strong>" . $count_errors . "</strong> errors. In case errors found, please check your dashboard!"; 
echo $insert_messages; 
$conn->close(); 
?> 

所有这些代码是一个PHP文件里,作为一个的cronjob运行! 现在的问题和我的问题是,我没有看到UPDATE正确运行或根本不运行,因为date_modified在我的数据库中始终是NULL,这是初始化值..我错过了什么? (一般我能做什么,以解决整个代码,如果有一个以上的错误吗?)

在此先感谢

一个产品(希腊XML)XML样本

<mystore> 
<created_at>2017-07-26 16:01:20</created_at> 
<products> 
<product> 
<id>9307</id> 
<name> 
<![CDATA[ Minimum ανδρικό t-shirt φλάμα Percy ivory ]]> 
</name> 
<link> 
<![CDATA[ 
https://www.mydomain.gr/andrika-rouxa/tshirts-andrikes-mployzes/minimum-andriko-t-shirt-percy-ivory.html 
]]> 
</link> 
<image> 
<![CDATA[ 
https://www.mydomain.gr/images/detailed/51/minimum-andriko-t-shirt-percy-122690105_(1).jpg 
]]> 
</image> 
<sku> 
<![CDATA[ 122690105-wh ]]> 
</sku> 
<mpn> 
<![CDATA[ 122690105-wh ]]> 
</mpn> 
<category id="30"> 
<![CDATA[ ΑΝΔΡΙΚΑ > T- shirts ]]> 
</category> 
<price>27.30</price> 
<description> 
<![CDATA[ 
<ul><li>χρώμα ελεφαντόδοντου</li><li>στρογγυλή λαιμόκοψη</li><li>στρογγυλεμένο και μακρύτερο πίσω μέρος</li><li>regular fit</li><li>100% cotton</li></ul> 
]]> 
</description> 
<instock>Y</instock> 
<availability>Σε απόθεμα</availability> 
<manufacturer> 
<![CDATA[ Minimum ]]> 
</manufacturer> 
<size>L,XL</size> 
<sex> 
<![CDATA[ Άνδρας ]]> 
</sex> 
</product> 
</products> 
</mystore> 

date_modified is varchar(128)在我的数据库 - utf8_general_ci 我不认为这是一个问题,对不对?

+0

@Parfait我编辑我的问题..感谢您花时间回复.. –

+0

哪个'UPDATE'不起作用?循环之前的第一个或带有INSERT的那个?请解释什么工作。除了* date_modified *之外,记录是否追加和更新?如果你声明这个字段是'varchar',那么即使你传递了一个整数,第一个更新也不会失败,因为MySQL会根据这个整数进行转换。 – Parfait

+0

请注意您的'INSERT'不会触及* date_modified *,只* date_added *。所以这些记录对于* date_modified *是'NULL'。仔细检查你的数据并报告具体问题。 – Parfait

回答

1

考虑使用的产品但仅用于存储XML数据的products_temp表,具体结构。从那里运行需要追加和更新查询从临时表迁移到最终表。

绝对如果这里有任何外卖,请使用parameterized queries,它避免引用附件和变量级联以获得更清洁,更安全,可维护的代码。

XML数据处理(追加内循环查询)

// CLEAN OUT TEMP TABLE 
$sql = 'DELETE FROM products_temp'; 
$delete_xml = $conn->query($sql); 

// PREPARED STATEMENT 
$sql = 'INSERT INTO products_temp (business_id, pid, `name`, `category`, product_link, price, 
            size, color, weight, `description`, manufacturer, mpn, ean, 
            image, sku, instock, availability, `status`, date_added) 
     VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'; 

// APPEND ALL RAW XML DATA INTO TEMP TABLE (IN LOOP, WITHOUT INNER IF LOGIC) 
//...same xml objects 

while($reader->read()) { 
    if($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'product') { 
     //...same xml variables 
     $product = new SimpleXMLElement($reader->readOuterXml()); 
     $stmt = $conn->prepare($sql); 

     $stmt->bind_param("sssssssssssssssssss", 
          mysqli_real_escape_string($conn,stripslashes($pid)), 
          mysqli_real_escape_string($conn,stripslashes($name)), 
          mysqli_real_escape_string($conn,stripslashes(trim($category_path))), 
          $check_product_url, 
          mysqli_real_escape_string($conn,stripslashes($price)), 
          mysqli_real_escape_string($conn,stripslashes(trim(strtolower($size)))), 
          mysqli_real_escape_string($conn,stripslashes(trim(strtolower($color)))), 
          mysqli_real_escape_string($conn,stripslashes(trim($weight))), 
          mysqli_real_escape_string($conn,stripslashes(trim($description))), 
          mysqli_real_escape_string($conn,stripslashes(trim(strtolower($manufacturer)))), 
          mysqli_real_escape_string($conn,stripslashes(trim($mpn))), 
          mysqli_real_escape_string($conn,stripslashes(trim($ean))), 
          $product_image, 
          mysqli_real_escape_string($conn,stripslashes(trim($sku))), 
          mysqli_real_escape_string($conn,stripslashes($instock)), 
          mysqli_real_escape_string($conn,stripslashes($availability)), 
          $status, 
          $date); 

     $stmt->execute(); 
    } 
} 

温度数据处理(外循环中,每个调用一次,避免了使用阵列和其他foreach

使用WHERE NOT EXISTS

// APPEND ONLY NEW TEMP PRODUCTS WITH RELEVANT INFO AND NOT IN SPECIAL CATEGS INTO PRODUCTS 
$sql = 'INSERT INTO products (business_id, pid, `name`, `categor`y, product_link, price, 
           size, color, weight, `description`, manufacturer, mpn, ean, 
           image, sku, instock, availability, `status`, date_added) 
     SELECT t.business_id, t.pid, t.name, t.category, t.product_link, t.price, 
       t.size, t.color, t.weight, t.description, t.manufacturer, t.mpn, t.ean, 
       t.image, t.sku, t.instock, t.availability, t.status, t.date_added 
     FROM products_temp t 
     WHERE NOT EXISTS (SELECT 1 FROM products sub 
          WHERE sub.p_id = t.p_id AND sub.business_id = t.business_id) 
      AND t.image IS NOT NULL AND t.price IS NOT NULL AND t.name IS NOT NULL 
      AND t.link IS NOT NULL AND t.manufacturer IS NOT NULL 
      AND t.category_id NOT IN (604, 613, 635)'; 
$insert_business_xml = $conn->query($sql); 

使用UPDATE INNER JOIN

// UPDATE MATCHED TEMP PROUCTS WITH MISSING RELEVANT INFO OR IN SPECIAL CATEGS (I.E., ERRORS) 
$sql = 'UPDATE products p INNER JOIN products_temp t 
          ON p.p_id = t.p_id AND p.business_id = t.business_id 
     SET p.status=0, p.date_modified = ? 
     WHERE t.image IS NULL OR t.price IS NULL OR t.name IS NULL 
      OR t.link IS NULL OR t.manufacturer IS NULL 
      OR t.category IN (604, 613, 635)'; 

$stmt = $conn->prepare($sql); 
$stmt->bind_param("s", $date_modified); 

$stmt->execute(); 
$count_errors = $mysqli->affected_rows;  // ERRORS FOR MESSAGE AT END 


// UPDATE EXISTING MATCHED TEMP PRODUCTS WITH RELEVANT INFO AND NOT IN SPECIAL CATEGS 
$sql = 'UPDATE products p INNER JOIN products_temp t 
          ON p.p_id = t.p_id AND p.business_id = t.business_id 
     SET p.business_id = t.business_id, p.name = t.name, p.category = t.category, 
      p.product_link = t.product_link, p.price = t.price, p.size = t.size, 
      p.color = t.color, p.weight = t.weight, p.description = t.description, 
      p.manufacturer = t.manufacturer, p.mpne = t.mpn, p.ean = t.ean, 
      p.image = t.image, p.sku = t.sku, p.instock = t.instock, 
      p.availability = t.availability, p.status = t.status, p.date_added = t.date_added 
     WHERE t.image IS NOT NULL AND t.price IS NOT NULL AND t.name IS NOT NULL 
      AND t.link IS NOT NULL AND t.manufacturer IS NOT NULL 
      AND t.category_id NOT IN (604, 613, 635)'; 
$update_business_xml = $conn->query($sql); 


// UPDATE EXISTING NON-MATCHED TEMP PRODUCTS 
$sql = 'UPDATE products p SET p.status = 0 
     WHERE NOT EXISTS (SELECT 1 FROM products_temp sub 
          WHERE sub.p_id = p.p_id AND sub.business_id = p.business_id)'; 
$update_business_xml = $conn->query($sql); 

注:当然没有实际的数据和数据库,这一切都是未经检验的。请调整任何被忽视的语法并集成到更大的代码库中。

+0

我想我明白什么准备和“ssssss”工作..你正在使用questionmarks ..?,?,?...在​​MySQL查询和之后,你正在使用准备 - >($ sql)和bind_param(“s ”,$ DATE_MODIFIED);你喜欢用变量替换s,对吗?但仍然有一些问题,虽然...我得到这个错误:“_italic_类型定义字符串中的元素数量与绑定变量的数量不匹配_italic_” 在您要说的这行代码中: $ stmt = $ conn- >制备($ SQL); $ stmt-> bind_param(“s”,$ date_modified); $ stmt-> execute(); $ count_errors = $ mysqli-> affected_rows; –

+0

如果我有一个“s”和一个“?”在mysql里面我应该有一个变量($ date_modified),对吧? –

+0

正确。请阅读关于php/mysqli参数化的大量离线/在线文档和教程。是'?'是占位符,'s'定义了* string *类型(对于* integer *类型使用'i')。至于错误,你在追加查询中传递了19个值,我计算了17,所以我又添加了两个问号和s。 – Parfait

相关问题