"Сериализация" SimpleXMLElement "не разрешена при сохранении в Wordpress post_meta

Я работаю над страницей wordpress для амазонки. Для этого я использую функцию aws_signed_request, чтобы получить цену и ссылку с amazon.

Вот функция aws_signed_request, возвращающая xml:

    function  aws_signed_request($region, $params, $public_key, $private_key, $associate_tag) {
    $method = "GET";
    $host = "ecs.amazonaws.".$region;
    $uri = "/onca/xml";

    $params["Service"]          = "AWSECommerceService";
    $params["AWSAccessKeyId"]   = $public_key;
    $params["AssociateTag"]     = $associate_tag;
    $params["Timestamp"]        = gmdate("Y-m-d\TH:i:s\Z");
    $params["Version"]          = "2009-03-31";

    ksort($params);

    $canonicalized_query = array();

    foreach ($params as $param=>$value)
    {
        $param = str_replace("%7E", "~", rawurlencode($param));
        $value = str_replace("%7E", "~", rawurlencode($value));
        $canonicalized_query[] = $param."=".$value;
    }

    $canonicalized_query = implode("&", $canonicalized_query);

    $string_to_sign = $method."\n".$host."\n".$uri."\n".
                            $canonicalized_query;

    /* calculate the signature using HMAC, SHA256 and base64-encoding */
    $signature = base64_encode(hash_hmac("sha256", 
                                  $string_to_sign, $private_key, True));

    /* encode the signature for the request */
    $signature = str_replace("%7E", "~", rawurlencode($signature));

    /* create request */
    $request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;

    /* I prefer using CURL */
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$request);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    $xml_response = curl_exec($ch);

   if ($xml_response === False)
    {
        return False;
    }
    else
    {
        $parsed_xml = @simplexml_load_string($xml_response);
        return ($parsed_xml === False) ? False : $parsed_xml;
    }
} 

После этого я получаю asin из сообщения и генерирую ссылку и цену

global $post;  
$asin = get_post_meta($post->ID, 'ASIN', true);

$public_key = 'xxxxxxxxxxx';
$private_key = 'xxxxxxxxxxx';
$associate_tag = 'xxxxxxxxxxx';

$xml = aws_signed_Request('de',
array(
  "MerchantId"=>"Amazon",
  "Operation"=>"ItemLookup",
  "ItemId"=>$asin,
  "ResponseGroup"=>"Medium, Offers"),
$public_key,$private_key,$associate_tag);

$item = $xml->Items->Item;

$link = $item->DetailPageURL;
$price_amount = $item->OfferSummary->LowestNewPrice->Amount;
if ($price_amount > 0) { 
    $price_rund = $price_amount/100;
    $price = number_format($price_rund, 2, ',', '.');
} else {
    $price= "n.v."; 
}

Все это работает очень хорошо, когда я повторяю $link и $price. Но я хочу сохранить значения в пользовательских полях сообщения Wordpress, поэтому мне не нужно запускать функцию каждый раз.

update_post_meta($post->ID, 'Price', $price);
update_post_meta($post->ID, 'Link', $link);

Это добавляет цену как правильное значение, но когда я хочу добавить ссылку, я получаю это сообщение об ошибке:

Невозможно исключить "Исключение" с сообщением "Сериализация" SimpleXMLElement" не разрешен в...

Но когда я удаляю функцию $parsed_xml =..., она сохраняет пустое значение.

Ответ 1

(Почти) все возвращенное, когда вы проходите объект SimpleXML, на самом деле является другим объектом SimpleXML. Это позволяет писать $item->OfferSummary->LowestNewPrice->Amount: запрос ->OfferSummary объекта $item возвращает объект, представляющий OfferSummary XML node, поэтому вы можете запросить ->LowestNewPrice на этом объекте и т.д. Обратите внимание, что это также относится к атрибутам - $someNode['someAttribute'] будет объектом, а не строкой!

Чтобы получить строковое содержимое элемента или атрибута, вам нужно "бросить" его, используя синтаксис (string)$variable. Иногда PHP знает, что вы хотите сделать это, и сделайте это за вас - например, при использовании echo - но в целом хорошая практика: всегда отсылать к строке вручную, чтобы вы выиграли ' У вас есть какие-либо сюрпризы, если вы позже измените свой код. Вы также можете использовать для целых чисел, используя (int), или float, используя (float).

Вторая часть вашей проблемы состоит в том, что объекты SimpleXML хранятся довольно специально в памяти и не могут быть "сериализованы" (т.е. превращены в строку, полностью описывающую объект). Это означает, что если вы попытаетесь сохранить их в базе данных или сеансе, вы получите сообщение об ошибке, которое вы видите. Если вы действительно хотели сохранить целый блок XML, вы можете использовать $foo->asXML().

Итак, короче:

  • используйте $link = (string)$item->DetailPageURL;, чтобы получить строку, а не объект
  • используйте update_post_meta($post->ID, 'ItemXML', $item->asXML());, если вы хотите сохранить весь товар