8 Replies Latest reply on Oct 27, 2009 2:41 PM by mewk

    problems returning complex objects from a php data service

    mewk Level 3

      either the data services tool is buggy or i am doing something wrong. here is the code:

       

       

      <?xml version="1.0" encoding="utf-8"?>
      <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
           xmlns:s="library://ns.adobe.com/flex/spark"
           xmlns:mx="library://ns.adobe.com/flex/halo"
           minWidth="1024" minHeight="768"
           xmlns:personservice="services.personservice.*"
           initialize="init()">
           
           <fx:Script>
                <![CDATA[
                     import mx.rpc.events.ResultEvent;
                     import mx.controls.Alert;
                     import mx.collections.ArrayCollection;
                
                     public var people:ArrayCollection;
                     
                     private function init():void {
                          getPeopleInMyWorldResult.token = personService.getPeopleInMyWorld();
                     }
      
      
                     protected function getPeopleInMyWorldResult_resultHandler(event:ResultEvent):void {
                          people = new ArrayCollection(event.result as Array);
                     }
      
                ]]>
           </fx:Script>
           <fx:Declarations>
                <s:CallResponder id="getPeopleInMyWorldResult" result="getPeopleInMyWorldResult_resultHandler(event)"/>
                <personservice:PersonService id="personService" 
                     destination="PersonService" 
                     endpoint="http://localhost/photoapp/Test3-debug/gateway.php" 
                     fault="Alert.show(event.fault.faultString)" 
                     showBusyCursor="true" 
                     source="PersonService"/>
           </fx:Declarations>
           
      </s:Application>
      

       

      <?php
      
      class Person {
           public $name;
           public $cars;
      }
      class Car {
           public $year;
           public $make;
           public $model;
      }
      
      class PersonService {
           public function getPeopleInMyWorld() {
                $person1 = new Person();
                $person1->name = "John Doe";
                $car1 = new Car();
                $car1->year = 2005;
                $car1->make = 'audi';
                $car1->model = 'A6 Quattro';
                $car2 = new Car();
                $car2->year = 1970;
                $car2->make = 'datsun';
                $car2->model = '510';
                $person1->cars = array($car1, $car2);
      
                $person2 = new Person();
                $person2->name = "Jane Doe";
      
                return array($person1, $person2);
           }
      }
      

       

      create a new "flex" project in FB Beta1 with a php server. Setup the application and php script as normal, then configure the return type for the getPeopleInMyWorld function. I created a new return type called "Person" and was quite please to see that FB automagically created a "Cars" class with the all the right properties.

       

      Unfortunately, if you run the code (try debug mode and put a breakpoint on the result handler) you'll notice that "john doe" has lost his cars and that you also get the silent (check console) error:

      TypeError: Error #1034: Type Coercion failed: cannot convert []@1226bc49 to mx.collections.ArrayCollection.
      

      any ideas??

       

      i can get this to work by using json, but it's extra work, the com.adobe.serializers.json.JSONDecoder has little documentation, and the method outlined above is just begging to work.

       

      so, how are the rest of you getting complex data back from your servers? json?? amfphp?? xml (but surely not)??

       

       

      also, since i'm here discussing data services, if any adobe ppl are about, please throw one extra voice behind the following feature requests:

      1) support for optional service call arguments (http://bugs.adobe.com/jira/browse/FB-19659)

      2) a button for automatically 'generating service calls' from within the data services panel.

       

      thanks,

       

      - e

        • 1. Re: problems returning complex objects from a php data service
          Gaurav P(Adobe) Level 2

          Hi,

          We are working on supporting arrays from php directly, which will resolve the issue. You can find the bug at http://bugs.adobe.com/jira/browse/FB-21375.

          However, currently there is a workaround for this.

          Instead of returning array($person1, $person2) directly, use code similar to the following code:

           

                 $rows = new Zend_Amf_Value_Messaging_ArrayCollection();      

                  $rows->source = array($person1, $person2); //assign your intended array here

                 return $rows;

           

          This should resolve the issue for now.

           

          Thanks,

          - Gaurav

          1 person found this helpful
          • 2. Re: problems returning complex objects from a php data service
            Gaurav P(Adobe) Level 2

            Also, instead of using array directly at

            $person1->cars = array($car1, $car2);

            Use something like:

             

            $cars = new Zend_Amf_Value_Messaging_ArrayCollection();     

            $cars->source = array($car1, $car2);

            $person1->cars = $cars;

            1 person found this helpful
            • 3. Re: problems returning complex objects from a php data service
              mewk Level 3

              Thank you Gaurav for pointing me in the right direction. There was some debate in the blogs as to which data transferring method (amfphp, json, or xml) was best. See

              http://blogs.adobe.com/mikepotter/2006/07/php_and_flex_js.html

              and

              http://www.5etdemi.com/blog/archives/2006/12/clearing-the-fud-on-amfphps-speed-versus-json -and-xml/

              I used json yesterday

              php:  json_encode(array($p1, $p2));   // observation: you only have to encode once as opposed
                                                    // to using amf on each array...
              
              FB:   private var jsonD:JSONDecoder = new JSONDecoder();
                    var jsonString:String = {{{return result from service call}}}
                    myPeople:ArrayCollection = jsonD.decode(jsonString, services.personservice.Person);
              
              

               

              Note that in FB you can use the services.personservice.Person class as an optional argument in the jsonD.decode function. This class can be automatically generated using FB's built-in data service's panel when you try to configure the return type (as I described above). The json data should unserialize correctly with Cars objects automagically created and everything (a huge time saver!!).

               

              It worked for me, though I'm not sure how deep the unserialization process is capable of going (objects within objects w/in objects, for example). Also I had some trouble with adobe's jsonDecoder; it had trouble eating (uhm parsing) hollow objects (i.e. objects with null properties), whereas the php_encode / php_decode handled these objects w/o fail.

               

              Anyway, will be reading up on amf. Tanx again Gaurav,

               

              - e

              • 4. Re: problems returning complex objects from a php data service
                Gaurav P(Adobe) Level 2

                Well I would say that AMF as a messaging format is the fastest as it an optimized, compressed, binary format. In evaluating the speed we should also consider the overall time to process the encoding and decoding on client and server.

                 

                If you intend to use JSON, the best way would be to expose the php as a http service, which means the php will return a JSON when called though a url with given parameters either using HTTP Post or Http Get. For example you can write a wrapper php file which reads the function name from the GET url params and calls the relevant function on a php class, then encode it in JSON and return it as http response.

                Once this is done, you can use the Data services panel, and select HTTPService while creating a service. Create a operation by giving the name and the url(one which you configured above). Configure return type on the operation and you are done. Use this service as a equivalent of any other service (AMF or WebService).

                This will solve the problem of you coding against JSON Decoder.

                 

                >> observation: you only have to encode once as opposed  // to using amf on each array...

                Well this is a bug. The intention is that you won't have to do anything special like creating a Zend Array to create an array. All your usual ways of coding in PHP should work as it is. The use of Zend Array was just a workaround till we resolve this issue.

                 

                Thanks,

                - Gaurav

                • 5. Re: problems returning complex objects from a php data service
                  mewk Level 3

                  Hi,

                   

                  Could somebody please update me on the status of DCD and PHP services?

                   

                  Beta 2 has not fully resolved the issues outlined above or from here.

                   

                  I created two new PHP services based on the code at the top of this post (with some minor modifications). The first service returns an array of complex objects, while the second service uses Gaurav's workaround and returns a Zend array collection. Unfortunately, both services are buggy.

                   

                  While configuring the return type, both services work -- but when returning actual data, objects are dropped with the first service (i.e. no change from what I described before) and with Gaurav's workaround, internal objects are returned as generic objects instead of their specific type (i.e. returning a generic object where it should be of type Car).

                   

                  What is most confusing is that when the operation is tested from the data/services panel, the returned data is exactly as it should be (no missing properties and no generic object types).

                   

                  Just want to know if I should file a new bug or if the issue has already been addressed. I've attached the test cases, if needed.

                   

                  Thanks,

                   

                  - e

                  • 6. Re: problems returning complex objects from a php data service
                    mewk Level 3

                    I figure some illustrations might better communicate the problem.

                     

                    For the two service results, I've highlighted the problems in red. 'ServiceResults1.png' are the return results w/o Gaurav's workaround and you can see that the cars array is NULL. 'ServiceResults2.png' show the return results with Gaurav's workaround and you can see that generic objects are being returned (the fields in red should read valueObjects.Car and valueObjects.Tire instead).

                     

                    - e

                    • 8. Re: problems returning complex objects from a php data service
                      mewk Level 3

                      would if i could -- i get a "permission violation" error when try to access the link. wanna up my security clearance? (joking ...)

                       

                      - e