[英]How do I add/update xml attributes with Symfony Serializer using my class/object?
I have the following code example which defines a Contact class that can hold a name and a list of phone numbers. 我有以下代码示例,该示例定义了一个Contact类,该类可以包含名称和电话号码列表。 What I want to be able to do is set an attribute of "primary" on all the numbers, where the value for it is '1' for one of them arbitrarily, and '0' for the rest.
我想做的是在所有数字上设置一个“ primary”属性,其中任意一个数字的值为“ 1”,其余数字的值为“ 0”。
I'd really like to do this using a class method but couldn't find a way to do this using a setter - is it possible somehow? 我真的很想使用类方法来执行此操作,但找不到使用setter来执行此操作的方法-是否有可能?
Here's my code. 这是我的代码。 In it I:
在其中:
<?php
// Symfony Serializer experiment
require $_SERVER['DOCUMENT_ROOT'].'/libraries/symfony/vendor/autoload.php';
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
Class Number {
private $Number;
private $Type;
// Getters
public function getNumber()
{
return $this->Number;
}
public function getType()
{
return $this->Type;
}
// Setters
public function setNumber($number)
{
$this->Number = $number;
return $this;
}
public function setType($type)
{
$this->Type = $type;
return $this;
}
}
class Contact
{
private $Name;
private $Numbers = array();
function __construct() {
${@Primary} = 0;
}
// Getters
public function getName()
{
return $this->Name;
}
public function getNumbers()
{
return $this->Numbers;
}
// Setters
public function setName($name)
{
$this->Name = $name;
return $this;
}
public function setNumbers($numbers)
{
$this->Numbers = $numbers;
return $this;
}
public function addNumber($number) {
$this->Numbers['Number'][] = $number;
}
}
// Serializer setup
$xmlEncoder = new XmlEncoder();
$xmlEncoder->setRootNodeName('Contact');
$encoders = array($xmlEncoder, new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
// Create my object
$contact = new Contact();
$contact->setName('baa');
$number = new Number();
$number->setNumber('07878386123')->setType('Mobile');
$contact->addNumber($number);
// take a look at how it's stored
echo "<pre lang=xml>";
print_r($contact);
echo "</pre><br><br>";
// deserialize my desired xml into the same object
$data = <<<EOF
<Contact>
<Name>foo</Name>
<Numbers>
<Number primary='1'>
<Number>07878386459</Number>
<Type>Mobile</Type>
</Number>
<Number primary='0'>
<Number>02380860835</Number>
<Type>Landline</Type>
</Number>
</Numbers>
</Contact>
EOF;
$contact = $serializer->deserialize($data, Contact::class, 'xml', array('object_to_populate' => $contact));
// take a look at how it's stored
echo "<pre lang=xml>";
print_r($contact);
echo "</pre><br><br>";
// Add another number
$number = new Number();
$number->setNumber('02387345123')->setType('Landline');
$contact->addNumber($number);
// take a look at how it's stored
echo "<pre lang=xml>";
print_r($contact);
echo "</pre><br><br>";
// serialize to xml and see how the mixture of objects and arrays are treated
$xmlContent = $serializer->serialize($contact, 'xml');
$dom = new domDocument( '1.0', 'utf-8' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$result = $dom->loadXML($xmlContent);
$xmlContentFormatted=htmlentities($dom->saveXML());
?>
<pre lang=xml><?= $xmlContentFormatted ?></pre>
What I see in the output is: 我在输出中看到的是:
2) 2)
Contact Object
(
[Name:Contact:private] => baa
[Numbers:Contact:private] => Array
(
[Number] => Array
(
[0] => Number Object
(
[Number:Number:private] => 07878386123
[Type:Number:private] => Mobile
)
)
)
)
4) 4)
Contact Object
(
[Name:Contact:private] => foo
[Numbers:Contact:private] => Array
(
[Number] => Array
(
[0] => Array
(
[@primary] => 1
[Number] => 07878386459
[Type] => Mobile
)
[1] => Array
(
[@primary] => 0
[Number] => 02380860835
[Type] => Landline
)
)
)
6) Mixture of objects and arrays. 6)对象和数组的混合。 Could I code my Number class so that it uses an array rather than properties and have another method for setting attribute?
我可以对Number类进行编码,以便它使用数组而不是属性,并使用另一种设置属性的方法吗? (eg
(例如
$number->setNumber('07878386123')->setType('Mobile')->addAttr(array('primary' => '1'));
Contact Object
(
[Name:Contact:private] => foo
[Numbers:Contact:private] => Array
(
[Number] => Array
(
[0] => Array
(
[@primary] => 1
[Number] => 07878386459
[Type] => Mobile
)
[1] => Array
(
[@primary] => 0
[Number] => 02380860835
[Type] => Landline
)
[2] => Number Object
(
[Number:Number:private] => 02387345123
[Type:Number:private] => Landline
)
)
)
)
8) 8)
<?xml version="1.0"?>
<Contact>
<Name>foo</Name>
<Numbers>
<Number primary="1">
<Number>07878386459</Number>
<Type>Mobile</Type>
</Number>
<Number primary="0">
<Number>02380860835</Number>
<Type>Landline</Type>
</Number>
<Number>
<Number>02387345123</Number>
<Type>Landline</Type>
</Number>
</Numbers>
</Contact>
When deserializing from XML that has tags that use attributes, the php objects use arrays, so it would appear that if you want to start out with a php representation that can be given attributes you need to use arrays. 当从具有使用属性的标签的XML反序列化时,php对象使用数组,因此,如果要开始使用可以被赋予属性的php表示形式,则需要使用数组。
Quite an unsophisticated hack, but managed to find a way to make it work. 相当简单的骇客,但设法找到一种使之起作用的方法。 The modified example now does what I need:
修改后的示例现在可以满足我的需求:
<?php
// Symfony Serializer experiment
require $_SERVER['DOCUMENT_ROOT'].'/libraries/symfony/vendor/autoload.php';
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
// build datastructure as array
Class Number {
private $data;
public function __construct(array $attributes) {
$data = ['Number'];
foreach ($attributes as $name => $value) {
$this->data['Number']['@'.$name] = $value;
}
}
// Getters
public function getNumber()
{
return $this->data['Number']['Number'];
}
public function getType()
{
return $this->data['Number']['Type'];
}
public function get()
{
return $this->data['Number'];
}
// Setters
public function setNumber($number)
{
$this->data['Number']['Number'] = $number;
return $this;
}
public function setType($type)
{
$this->data['Number']['Type'] = $type;
return $this;
}
}
class Contact
{
private $data;
// Getters
public function getName()
{
return $this->data['Contact']['Name'];
}
public function getNumbers()
{
return $this->data['Contact']['Numbers'];
}
public function get()
{
return $this->data['Contact']; // this is the top level so return the Contact element, not data.
}
// Setters
public function setName($name)
{
$this->data['Contact']['Name'] = $name;
return $this;
}
public function setNumbers($numbers)
{
$this->data['Contact']['Numbers'] = $numbers;
return $this;
}
public function addNumber($number) {
$this->data['Contact']['Numbers']['Number'][] = $number;
}
}
// Serializer setup
$xmlEncoder = new XmlEncoder();
$xmlEncoder->setRootNodeName('Contact');
$encoders = array($xmlEncoder, new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$encoder = new \Symfony\Component\Serializer\Encoder\XmlEncoder();
// Create my object
$contact = (new Contact)->setName('Foo Bar');
$number = (new Number(array('primary'=>'1')))->setNumber('07878386123')->setType('Mobile');
$number_data = $number->get();
$contact->addNumber($number_data);
$number = (new Number(array('primary'=>'0')))->setNumber('02380876345')->setType('Landline');
$number_data = $number->get();
$contact->addNumber($number_data);
echo "<pre lang=xml>";
print_r($contact);
echo "</pre><br><br>";
$xmlContent = $serializer->serialize($contact->get(), 'xml');
$dom = new domDocument( '1.0', 'utf-8' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$result = $dom->loadXML($xmlContent);
$xmlContentFormatted=htmlentities($dom->saveXML());
?>
<pre lang=xml><?= $xmlContentFormatted ?></pre>
Output: 输出:
Contact Object
(
[data:Contact:private] => Array
(
[Contact] => Array
(
[Name] => Foo Bar
[Numbers] => Array
(
[Number] => Array
(
[0] => Array
(
[@primary] => 1
[Number] => 07878386123
[Type] => Mobile
)
[1] => Array
(
[@primary] => 0
[Number] => 02380876345
[Type] => Landline
)
)
)
)
)
)
<?xml version="1.0"?>
<Contact>
<Name>Foo Bar</Name>
<Numbers>
<Number primary="1">
<Number>07878386123</Number>
<Type>Mobile</Type>
</Number>
<Number primary="0">
<Number>02380876345</Number>
<Type>Landline</Type>
</Number>
</Numbers>
</Contact>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.