Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
585 views
in Technique[技术] by (71.8m points)

soap - PHP SoapVar Object Attribute?

Does anyone have any clue as to how I can add an attribute to a SoapVar object? It seems like it would be simple, but I can't get it to take/work.

I've looked at the PHP docs and at the following stackoverflow question:

Documentation on SoapVar,

stackoverflow question: SoapVar/Param and nested, repeated elements in SOAP

I'm trying to add an attribute like this array example, but using complex SoapVar objects instead.

<?php
 $amount['_'] = 25;
 $amount['currencyId'] = 'GBP';
 $encodded = new SoapVar($amount, SOAP_ENC_OBJECT);

?>

and end result wound be

<amount currencyId="GBP">25</amount> 

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Getting attributes into SOAP elements is a bit of a hassle. The way they implemented it is a bit confusing.

First thing to do is add the attributes to the wsdl file that SoapServer uses to correctly read and respond to the SOAP requests.

<xs:complexType name="encryptionContext">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            **<xs:attribute name="type" type="tns:encryptionType" />**
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

We will have to tell SoapServer to use a php helper class by passing it in the options as classmap:

$soap_server = new SoapServer($wsdl_file, array(
    'cache_wsdl' => 1,
    'trace' => true,
    'classmap' => array('mediaCollection' => 'SoapMediaHelper')
));

What we are mapping here is the SOAP element name mediaCollection to one of our classes, SoapMediaHelper. Instead of returning arrays, we can now return a class, in this case, it's named SoapMediaHelper. The class can have soap-element=>value pairs as well as soap-attribute=>value pairs.

Assuming we already have made a class that handles mediaCollections, this tells SoapServer to map a class called SoapMediaHelper to it. The class is really simple:

class SoapMediaHelper
{
    public function __construct(Array $properties = array())
    {
        foreach ($properties as $key => $value) {
            $this->{$key} = $value;
        }
    }
}

The properties of this class have to be populated. These properties should be both the tagname=>value pairs as well as the attribute name and value pair(s) for the attributes we want to add to our mediaCollection. SoapServer will figure out which is which according to our wsdl file.

We will still have to populate this object, which we can do with yet another class.

class SoapVarHelper
{
    public function get($the_playlist, $playlist_id, $owned_by_user){
        /* The SoapMediaHelper class is mapped to the mediaCollection wsdl.
         * This is only needed to be able to set attributes on the XML nodes while using php's SoapServer
         * */
        $media_helper = new SoapMediaHelper($the_playlist);
        /* For this type, the following xml attributes have to be set. (Not in the wsdl example above.) */
        if($playlist_id === 'playlists'){
            $media_helper->readOnly = false;
            $media_helper->userContent = true;
            $media_helper->renameable = false;
            $media_helper->canDeleteItems = true;
            
        }
        if($owned_by_user){
            $media_helper->readOnly = false;
            $media_helper->userContent = false;
            $media_helper->renameable = true;
            $media_helper->canDeleteItems = true;
            $media_helper->canReorderItems = true;
        }
        return new SoapVar($media_helper, SOAP_ENC_OBJECT);
    }
}

This class should be called with the normal tagname=>value pairs. It then adds the attributes we want. In this case conditionally. We feed our SoapMediaHelper object to SoapVar. (We told SoapServer earlier that this is fine.)

Now the last thing we need to do is, in our mediaCollection class, to use the helper SoapVarHelper to return a SoapMediaHelper (the one we told SoapServer about earlier).

In our mediaCollection we have a function get_metadata_for_root:

public function get_metadata_for_root($user_id, $index, $count){
    $titles = array(
        'slides' => 'Featured',
        
    );
    $media_metadata = array();
    foreach($titles as $key => $title){
        $playlist = array(
            'id' => $key,
            'title' => $title,
            'img' => $this->_utils->get_url() . '/public/sonos/images/browse-icons/icon-default-legacy.png'
        );
        **$media_metadata[] = $this->_soap_var_helper->get($playlist, $key, false);**
    }
    $res = array(
        'count' => count($media_metadata),
        'index' => 0,
        'total' => count($media_metadata),
        'mediaCollection' => $media_metadata
    );
}

For every mediaCollection result we pass it through the soap_var_helper to make sure not only the element=>value pairs are added, but also the attributes that we want on it.

TO SUMMARIZE:

  1. Make sure you feed the SoapServer with a wsdl file, so it know the elements and the attributes.

  2. In the SoapServer options add classmap in order to tell SoapServer that it is fine when we feed it a SoapMediaHelper object instead of the regular input.

  3. Before responding to a request for, in this case, mediaCollection, pass this response through the SoapMediaHelper. The SoapVarHelper will map all the properties=>value pairs as class properties, then the SoapMediaHelper will add attributes (also as name=>value pairs) to it.

  4. SoapServer will take care of the rest.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...