XML-парсер, использующий Shopify веб-перехватывающие позиции

Я использую shopify webhook для обновления поля qty на моем сервере sql при обновлении заказа, ниже мой код php

?php
$xmlData = fopen('php://input' , 'rb'); 
while (!feof($xmlData)) { $xmlString .= fread($xmlData, 4096); }
fclose($xmlData);
$xml = new SimplexmlElement($xmlString);


file_put_contents('orders/order' . '.xml', $xmlString);



$dom = new DomDocument();

$dom->load('orders/order.xml');

$itemList = $dom->getElementsByTagName('line-item');
foreach($itemList as $item) {
  $sku='';
  $qty='';
  foreach($item->childNodes as $child) {
    if ($child->localName == 'sku') {
      $sku = $child->textContent;
    }
    if ($child->localName == 'quantity') {
      $qty = $child->textContent;
    }
  }
  mysql_connect ("?????????????????????????");
mysql_select_db("??????????");

$query = "UPDATE xcart_categories SET product_count = product_count - $qty WHERE description='$sku';";

mysql_query($query);
}

и ниже - файл xml, который я получаю из интернет-магазина shopify

<?xml version="1.0" encoding="UTF-8"?>
<order>
  <buyer-accepts-marketing type="boolean">true</buyer-accepts-marketing>
  <closed-at type="datetime" nil="true"></closed-at>
  <currency>USD</currency>
  <email>[email protected]</email>
  <financial-status>pending</financial-status>
  <fulfillment-status>fulfilled</fulfillment-status>
  <gateway>Local Pick-Up</gateway>
  <id type="integer">140303247</id>
  <name>#1012</name>
  <note></note>
  <number type="integer">12</number>
  <subtotal-price type="decimal">0.2</subtotal-price>
  <taxes-included type="boolean">false</taxes-included>
  <total-discounts type="decimal">0.0</total-discounts>
  <total-line-items-price type="decimal">0.2</total-line-items-price>
  <total-price type="decimal">0.2</total-price>
  <total-price-usd type="decimal">0.2</total-price-usd>
  <total-tax type="decimal">0.0</total-tax>
  <total-weight type="integer">0</total-weight>
  <updated-at type="datetime">2012-09-16T21:20:07-04:00</updated-at>
  <created-at type="datetime">2012-09-16T21:08:30-04:00</created-at>
  <token>dcf523d93c68159c15a7c8d1fabbee07</token>
  <landing-site>/products/test</landing-site>
  <referring-site></referring-site>
  <cancelled-at type="datetime" nil="true"></cancelled-at>
  <cancel-reason nil="true"></cancel-reason>
  <cart-token>a9a7bc5d8103f6a3bb45e827f0cb8928</cart-token>
  <browser-ip nil="true"></browser-ip>
  <landing-site-ref nil="true"></landing-site-ref>
  <order-number type="integer">1012</order-number>
  <discount-codes type="array"/>
  <note-attributes type="array">
  </note-attributes>
  <processing-method>manual</processing-method>
  <line-items type="array">
    <line-item>
      <id type="integer">228531213</id>
      <requires-shipping type="boolean">false</requires-shipping>
      <fulfillment-service>manual</fulfillment-service>
      <grams type="integer">0</grams>
      <price type="decimal">0.2</price>
      <quantity type="integer">1</quantity>
      <sku>1234567</sku>
      <title>test</title>
      <product-id type="integer">104663831</product-id>
      <variant-id type="integer">240660979</variant-id>
      <vendor>5 Second</vendor>
      <variant-title nil="true"></variant-title>
      <fulfillment-status>fulfilled</fulfillment-status>
      <name>test</name>
      <variant-inventory-management></variant-inventory-management>
      <properties type="array">
      </properties>
    </line-item>
  </line-items>
  <shipping-lines type="array"/>
  <tax-lines type="array">
    <tax-line>
      <title>NY State Tax</title>
      <price type="decimal">0.0</price>
      <rate type="float">0.04</rate>
    </tax-line>
    <tax-line>
      <title>Queens County Tax</title>
      <price type="decimal">0.0</price>
      <rate type="float">0.04875</rate>
    </tax-line>
  </tax-lines>
  <billing-address>
    <first-name>Yeongju</first-name>
    <last-name>Lee</last-name>
    <address1>14809 northern blvd</address1>
    <address2></address2>
    <city>Flushing</city>
    <company></company>
    <country>United States</country>
    <phone></phone>
    <province>New York</province>
    <zip>11354</zip>
    <latitude type="decimal">40.76529</latitude>
    <longitude type="decimal">-73.81831</longitude>
    <name>Yeongju Lee</name>
    <country-code>US</country-code>
    <province-code>NY</province-code>
  </billing-address>
  <fulfillments type="array">
    <fulfillment>
      <id type="integer">67712419</id>
      <order-id type="integer">140303247</order-id>
      <created-at type="datetime">2012-09-16T21:20:07-04:00</created-at>
      <updated-at type="datetime">2012-09-16T21:20:07-04:00</updated-at>
      <tracking-number nil="true"></tracking-number>
      <tracking-company nil="true"></tracking-company>
      <status>success</status>
      <service>manual</service>
      <tracking-url>http://www.google.com/search?q=</tracking-url>
      <receipt>
      </receipt>
      <line-items type="array">
        <line-item>
          <id type="integer">228531213</id>
          <requires-shipping type="boolean">false</requires-shipping>
          <fulfillment-service>manual</fulfillment-service>
          <grams type="integer">0</grams>
          <price type="decimal">0.2</price>
          <quantity type="integer">1</quantity>
          <sku>1234567</sku>
          <title>test</title>
          <product-id type="integer">104663831</product-id>
          <variant-id type="integer">240660979</variant-id>
          <vendor>5 Second</vendor>
          <variant-title nil="true"></variant-title>
          <fulfillment-status>fulfilled</fulfillment-status>
          <name>test</name>
          <variant-inventory-management></variant-inventory-management>
          <properties type="array">
          </properties>
        </line-item>
      </line-items>
    </fulfillment>
  </fulfillments>
  <customer>
    <id type="integer">96489088</id>
    <email>[email protected]</email>
    <accepts-marketing type="boolean">true</accepts-marketing>
    <first-name>Yeongju</first-name>
    <last-name>Lee</last-name>
    <orders-count type="integer">12</orders-count>
    <total-spent type="decimal">16.26</total-spent>
    <note nil="true"></note>
    <created-at type="datetime">2012-08-17T11:31:50-04:00</created-at>
    <updated-at type="datetime">2012-09-16T21:20:07-04:00</updated-at>
    <state>enabled</state>
    <last-order-id type="integer">140303509</last-order-id>
    <tags>C</tags>
    <last-order-name>#1013</last-order-name>
  </customer>

like you see i got two sku and qty because of duplicated line-item so for example when customer order one "product name - test in this case i got "-2" quantity update in my sql server sku test field , but when i am using webhook event when order creation it worked i mean i see only one line item but all the other cases(when order updated, when order payment, when order fullfillment..) show me duplicated line item even there is only one item ordered i think i am parsing my XML badly anyone who can teach me correct code to pull 'line items' from the first line-items node i will really appreciate it! Thanks..again


person Max    schedule 19.09.2012    source источник


Ответы (1)


Вы делаете много лишних шагов, чтобы проанализировать там свой XML. Вам не нужно сохранять данные в файл перед его обработкой, и у вас есть случайный вызов SimpleXML, который вы не используете. Все, что вам нужно, это:

$xmlString = file_get_contents('php://input');
$dom = new DomDocument();
$dom->loadXML($xmlString);

После этого ваша логика синтаксического анализа выглядит нормально, но вы всегда выполняете только один SQL-запрос с одним SKU в нем.

Внутри вашего foreach цикла вы определяете переменные $sku и $qty, но вы ничего не делаете с ними внутри цикла. Так что в следующий раз в цикле вы перепишете их значения, и ничего не узнает о старых значениях.

Есть несколько способов сделать это:

  • запускать SQL внутри цикла (не очень эффективно)
  • создать массив артикулов и количеств ($sku[] = ...; $qty[] = ...;), а затем построить свой SQL из этих массивов
  • немного аккуратнее, создайте единый массив с парами SKU-количество в виде вложенных массивов ($sku_list[] = array('sku' => ..., 'qty' => ...))
  • Постройте строку SQL постепенно внутри цикла ($sql .= '...') и выполните ее один раз в конце
person IMSoP    schedule 20.09.2012
comment
Спасибо, IMSoP. Не могли бы вы показать мне конкретный код, чтобы я мог понять, что вы имеете в виду ... еще раз спасибо - person Max; 21.09.2012
comment
@Max Вместо foreach($itemList as $item) { $sku=''; $qty=''; /* [find SKU and Qty] */ } $sql = "UPDATE ... $sku ... $qty ..."; нужно сделать что-то вроде (вариант 3) $sku_list=array(); foreach($itemList as $item) { $sku=''; $qty=''; /* [find SKU and Qty] */ $sku_list[] = array('sku' => $sku, 'qty' => $qty)); } $sql=''; foreach ( $sku_list as $sku_pair ) { $sql .= "UPDATE ... {$sku_pair['sku']} ... {$sku_pair['qty']} ..."; - person IMSoP; 21.09.2012