2016-12-09 5 views
1

Итак, после некоторого изучения мне удалось проанализировать некоторый XML, который я получаю через Guzzle через simplexml_load_string. Проблема в том, что когда я потом попытаюсь отправить задание для каждого из детей, используя следующий код, я получаю сообщение об ошибке «Сериализация« SimpleXMLElement »не допускается».Невозможно сериализовать SimpleXMLElement в Laravel job

$parent = $this->getParent($keywords); 
foreach ($parent->children() as $child) { 
    dispatch(new ProcessChild($event, true), $this->otherVar); 
} 

Чтобы исправить это, я могу использовать следующий трюк для преобразования XML в массив;

json_decode(json_encode($child)) 

однако, в то время как это означает, что я могу отправить данные на новое место работы, это означает, что, насколько я могу работать, у меня нет никакого способа, чтобы получить доступ к @attributes. Альтернативой может быть что-то вроде следующего:

// ParentJob 
    $parent = $this->getParent($keywords); 
    foreach ($parent->children() as $child) { 
     dispatch(new ProcessChild($child->asXML, true), $this->otherVar); 
    } 

// ChildJob 
    public function __construct($xml, $otherVar) 
    { 
     $this->xml = simplexml_load_string($xml); 
     $this->otherVar = $otherVar; 
    } 

однако он все еще бросает ошибку сериализации на рассылку по какой-то причине, что я не могу работать, так как sould посылать только необработанный XML, а не объект.

Итак, мой главный вопрос: каким будет правильный способ передачи и дочерний SimpleXMLObject для работы в Laravel 5.3?

(не хватает чего-то, как перекручивание через все узлы/атрибуты и строить мой собственный набор из них)

ответ

0

Как выясняется, всю причину она не работала была из-за меня, используя simplexml_load_string() на конструктор дочерних заданий, который превращал его в simpleXMLElement до того, как задание было фактически сериализовано и помещено в очередь. правильный способ сделать это состоял в том, чтобы проанализировать XML-строку в методе дескриптора, которая выполняется после того, как задание было вытащено из очереди для фактической обработки.

Теперь это работает, я могу просто отправить дочернее задание с помощью $ child-> asXML и проанализировать его, когда работа на самом деле обрабатывается, то есть я все еще могу использовать все отличные функции simpleXML, такие как attributes().

Пример ParentJob:

foreach ($parent->children() as $child) { 
    dispatch(new ProcessChild($event, true), $this->otherVar); 
} 

Пример ChildJob:

protected $xml; 
protected $otherVar; 

public function __construct($xml, $otherVar) 
{ 
    $this->xml = $xml; 
    $this->otherVar = $otherVar; 
} 

public function handle() 
{ 
    $child = simplexml_load_string($this->xml); 
    $attributes = $child->attributes(); 
} 
+0

$ xml передается дочернему заданию с ($ child-> asXML()). Но я не могу использовать 'simplexml_load_string ($ this-> xml);'. Он говорит ту же ошибку. Сериализация «SimpleXMLElement» не допускается. У вас есть идеи? –

0

SimpleXmlElement можно преобразовать в массив следующим образом:

$xml = <<<'XML' 
<root> 
    <x a="a1">1</x> 
    <y b="b2">2</y> 
    <z>3</z> 
</root> 
XML; 

$xe = simplexml_load_string($xml); 
$a = $xe->xpath('*'); 
$a = array_map(function ($e) { 
    $item = (array) $e; 
    $item['nodeName'] = $e->getName(); 
    return $item; 
}, $a); 
// Now `$a` is an array (serializable object) 
echo json_encode($a, JSON_PRETTY_PRINT); 

Выход

[ 
    { 
     "@attributes": { 
      "a": "a1" 
     }, 
     "0": "1", 
     "nodeName": "x" 
    }, 
    { 
     "@attributes": { 
      "b": "b2" 
     }, 
     "0": "2", 
     "nodeName": "y" 
    }, 
    { 
     "0": "3", 
     "nodeName": "z" 
    } 
] 

Примечание: вы можете получить строковое значение SimpleXmlElement, переведя его в строку:

$item['value'] = (string) $e; 

Поскольку xpath метод поддерживает относительные выражения XPath, звездочка должна работать даже с пространствами имен XMLs. Подумайте об использовании расширения DOM, так как он намного более гибкий, чем SimpleXML. В частности, его DOMXPath класс позволяет register пространств имен и использовать зарегистрированные идентификаторы в выражениях XPath:

$xpath->registerNamespace('myprefix', 'http://example.com/ns'); 
$xpath->query('/root/myprefix:*'); 
+0

"В частности, его DOMXPath класс позволяет регистрировать и использовать пространство имен зарегистрированных идентификаторов в выражениях XPath". SimpleXML имеет такую ​​же функциональность, используя метод '-> registerXPathNamespace' (http://php.net/manual/en/simplexmlelement.registerxpathnamespace.php) – IMSoP

+0

Правильно, но вы должны иметь в виду, что регистрация будет только действительны для объектов, вы вызвали метод register *. Это означает, что в SimpleXML вам придется делать это снова и снова. – ThW

1

Преобразование XML в JSON, что путь означает потерю данных. Я предлагаю хранить XML, если это возможно.

SimpleXMLElement::asXML() - это способ. Не забудьте скобки.

$parent = $this->getParent($keywords); 
foreach ($parent->children() as $child) { 
    dispatch(new ProcessChild($child->asXML(), true), $this->otherVar); 
} 

Вызов как свойство означает, что SimpleXML пытается интерпретировать его как дочерний элемент. Это означает, что это будет (пустой) SimpleXMLElement.

Вот небольшой пример, показывающий поведение:

$node = new SimpleXMLElement('<foo/>'); 
var_dump($node->asXml); 
var_dump($node->asXml->getName()); 
var_dump($node->asXml()); 

Выход:

object(SimpleXMLElement)#2 (0) { 
} 
string(0) "" 
string(29) "<?xml version="1.0"?> 
<foo/> 
" 
Смежные вопросы