我有以下代码示例,它定义了一个可以保存姓名和电话号码列表的Contact类。我想要做的是设置" primary"的属性。在所有数字上,其值为' 1'其中一个是任意的,' 0' 0其余的。
我真的很喜欢使用类方法来做这件事,但是找不到使用setter做到这一点的方法 - 是否可能以某种方式?
这是我的代码。在其中我:
<?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>
我在输出中看到的是:
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)
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)对象和数组的混合。我可以编码我的Number类,以便它使用数组而不是属性,并有另一种方法来设置属性? (例如
$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)
<?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>
当从具有使用属性的标签的XML反序列化时,php对象使用数组,因此如果你想从可以赋予属性的php表示开始,你需要使用数组。
答案 0 :(得分:1)
相当不成熟的黑客,但设法找到一种方法使其工作。修改后的例子现在可以满足我的需求:
<?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>
输出:
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>