I'm using a SoapClient (zend2), but for some reasons, can't get complete data answer
$client = new \SoapClient($host);
$result = $client->getInvoice();
$result var_dump:
["ListInvoiceResult"] => object(stdClass)#282 (4) {
["Status"] => int(1)
["ErrorCode"] => NULL
["ErrorMessage"] => string(0) ""
["Invoice"] => array(1436) {
[0] => object(stdClass)#283 (3) {
["ID"] => int(12741)
["Date"] => string(10) "2011.01.31"
["DateSales"] => string(10) "2011.01.31"
}
Above object missing a variable InvoiceNumber
But when I call __getLastResponse method , I've recieved complete data with InvoiceNumber
<p1:Invoice>
<p1:ID>12741</p1:ID>
<p1:InvoiceNumber>1|FA|2011|00633</p1:InvoiceNumber>
<p1:Date>2011.01.31</p1:Date>
<p1:DateSales>2011.01.31</p1:DateSales>
</p1:Invoice>
Hmmm. Looks strange. But all other methods returns complete data, even variable Invoice Number..
I think you should try using the classmap option in SoapClient or check you mapped classes, for instance:
class MyBook {
public $title;
public $author;
}
$server = new SoapClient("books.wsdl", array('classmap' => array('book' => "MyBook")));
In your case you should model ListInvoiceResult and Invoice class for instance:
class WS_ListInvoiceResult {
public $Status;
public $ErrorCode;
public $ErrorMessage;
public $Invoice;
}
class WS_Invoice {
public $ID;
public $Date;
public $DateSales;
public $InvoiceNumber;
}
And connect to soap api as such:
$server = new SoapClient("wsdl path", array('classmap' => array("ListInvoiceResult" => "WS_ListInvoiceResult", "Invoice" => "WS_Invoice")));
If this doesn't help try checking your WSDL, though based on the response it appears to be OK.
Related
all. I am working on a custom-build API built in PHP. I have an array (see below) that has been returned from my database access object. When I use the json_encode function, the int value assigned to phone1Type gets encoded incorrectly. I have tried this with multiple records, and the value in the encoded json object always matches the phone2Type. Any ideas as to what might be going on? (I've included two sample arrays below in addition to their corresponding json object.)
The code that I'm using to check the array and json values is the following:
$responseObject = $userCtrl->selectPersonForUserId($userId);
var_dump($responseObject);
var_dump(json_encode($responseObject));
One example array to encode is as follows. (The phone1Type and phone2Type keys are at the very end, but include the full array here for completeness. Also, as a side note, the other int values in the array are encoding fine.)
object(Adult)#13 (8) {
["person":protected]=>
object(Person)#14 (4) {
["id":protected]=>
int(3)
["firstName":protected]=>
string(7) "William"
["lastName":protected]=>
string(3) "Smith"
["hasVerified":protected]=>
bool(false)
}
["address":protected]=>
object(Address)#17 (4) {
["id":protected]=>
int(2)
["address1":protected]=>
string(15) "520 Hilbert Dr."
["address2":protected]=>
string(0) ""
["city":protected]=>
object(City)#18 (3) {
["zip":protected]=>
string(5) "71342"
["city":protected]=>
string(11) "West Monroe"
["state":protected]=>
string(2) "AL"
}
}
["email":protected]=>
string(14) "wmrmay#spam.com"
["phone1":protected]=>
string(10) "6195080000"
["phone1Type":protected]=>
int(1)
["phone2":protected]=>
string(10) "3188126574"
["phone2Type":protected]=>
int(0)
["teacher":protected]=>
NULL
}
This encodes to the following json object:
{"person":{"id":3,"firstName":"William","lastName":"Smith","hasVerified":false},"address":{"id":2,"address1":"520 Hilbert Dr.","address2":"","city":{"zip":"71342","city":"West Monroe","state":"AL"}},"email":"wmrmay#spam.com","phone1":"6195080000","phone1Type":0,"phone2":"3188126574","phone2Type":0,"teacher":null}
For brevity, here's the last few lines of another array followed by its json counterpart:
["email":protected]=>
string(20) "wltrallen2#gmail.com"
["phone1":protected]=>
string(10) "6192047586"
["phone1Type":protected]=>
int(1)
["phone2":protected]=>
NULL
["phone2Type":protected]=>
NULL
["teacher":protected]=>
NULL
"email":"wltrallen2#gmail.com","phone1":"6192047586","phone1Type":null,"phone2":null,"phone2Type":null,"teacher":null}
Edited to add original Adult.php model class:
class Adult implements JsonSerializable {
protected $person; // Person object
protected $address; // Address object
protected $email;
protected $phone1;
protected $phone1Type; // PhoneType object
protected $phone2;
protected $phone2Type; // PhoneType object
protected $teacher; // Teacher object
public function __construct($person, $address, $email, $phone1, $phone1Type, $phone2, $phone2Type, $teacher)
{
$this->person = $person;
$this->address = $address;
$this->email = $email;
$this->phone1 = $phone1;
$this->phone1Type = $phone1Type;
$this->phone2 = $phone2;
$this->phone2Type = $phone2Type;
$this->teacher = $teacher;
}
... // Getters and Setters removed for brevity
private function getPhoneType($type) {
if(PhoneTypes::isValid($type)) {
return PhoneTypes::StringDict[$type];
}
return '';
}
function jsonSerialize() {
$array = [
'person' => $this->person,
'address' => $this->address,
'email' => $this->email,
'phone1' => $this->phone1,
'phone1Type' => $this->phone2Type,
'phone2' => $this->phone2,
'phone2Type' => $this->phone2Type,
'teacher' => $this->teacher
];
return $array;
}
}
So, embarrassingly, this was just caused by an initial typo and then forgetfulness on my part.
In the Adult.php model class, I has implemented the JsonSerializable interface to make sure that an Adult object could be encoded in Json. When doing so, I made a typographical error when building the array:
'phone1Type' => $this->phone2Type,
which should have been, of course...
'phone1Type' => $this->phone1Type,
This typo was the source of my issue. Ugh!
However, as I've been deeply mired in this project and it had been some time since I originally built those model classes, I had completely forgot that for an object to be encodable by JSON that it had to implement the JsonSerializable interface. So, as I was debugging, it never occurred to me to look back in my model at the very end of the file to examine the jsonSerialize() function. (Insert face palm here.)
Thank you for your responses. This is the first time that I've actually gotten to post a question on stackOverflow, and I appreciate you all taking a look. Sorry that it wasn't an exciting question and merely a silly novice programmer moment.
I'm working on an integration for Netsuite. When I return my saved search, there are 300+ fields returned for the searchRowBasic property. I'll include a var_dump below.
My source code is from Magento 2, so the factory methods are out of scope, but you can assume they create a new instance of the class (which i'll note).
I'm also using the composer package for netsuite to utilize namespaces rather than Netsuite's official package that is one file with 1600 classes and no namespaces (seriously).
/** #var Netsuite\Classes\ItemSearchAdvanced $searchRecord */
$searchRecord = $this->itemSearchAdvancedFactory->create();
/** #var Netsuite\Classes\SearchRow $searchRow */
$searchRow = $this->itemSearchRowFactory->create();
/** #var Netsuite\Classes\SearchRowBasic $searchRowBasic */
$searchRowBasic = $this->itemSearchRowBasicFactory->create();
/** #var Netsuite\Classes\SearchRequest */
$request = $this->searchRequestFactory->create();
$searchRecord->savedSearchId = 190;
$request->searchRecord = $searchRecord;
/** #var Netsuite\NetsuiteService $netsuiteService */
// Loaded with authentication values.
$netsuiteService = $this->getNetsuiteService();
$netsuiteService->setSearchPreferences(false, 1000);
// Submit the request - returns successful response.
$searchResponse = $netsuiteService->search($request);
My Request returns a successful response (:thumbsup:)
The problem is that I want to use 4 variables in the entire response, but there are hundreds of indexes in the array that are unused. My biggest concern is that Netsuite is querying these during the response, my secondary concern is returning multiple KB's of data that I won't use within my response for larger requests.
I have tried this, to unset the parameters, hoping that if I undeclared them, Netsuite would ignore them in the response, but I had no luck.
protected function getSearchRecord(): ItemSearchAdvanced
{
$searchRecord = $this->itemSearchAdvancedFactory->create();
$searchRow = $this->itemSearchRowFactory->create();
$searchRowBasic = $this->itemSearchRowBasicFactory->create();
$i = 0;
$fields = $searchRowBasic::$paramtypesmap;
foreach ($fields as $name => $type) {
// use only the first 10 just to see if only these 10 will be used.
// no such luck.
if ($i > 10) {
unset($searchRowBasic::$paramtypesmap[$name]);
unset($searchRowBasic->$name);
}
$i++;
}
$searchRow->basic = $searchRowBasic;
$searchRecord->columns = $searchRow;
return $searchRecord;
}
Question:
I know the fields I want to return before I make the request. How can I specify those fields to only return the data I need, not all the data available?
Here is a var_dump of the response to see the format. I truncated the data a good amount, if anyone needs more I can easily provide it, but I think there is enough info provided currently.
class NetSuite\Classes\SearchResponse#2452 (1) {
public $searchResult =>
class NetSuite\Classes\SearchResult#2449 (8) {
public $status =>
class NetSuite\Classes\Status#2447 (2) {
public $statusDetail =>
NULL
public $isSuccess =>
bool(true)
}
public $totalRecords =>
int(1)
public $pageSize =>
int(1000)
public $totalPages =>
int(1)
public $pageIndex =>
int(1)
public $searchId =>
string(60) "<requst_id_with_personal_data>"
public $recordList =>
NULL
public $searchRowList =>
class NetSuite\Classes\SearchRowList#2475 (1) {
public $searchRow =>
array(1) {
[0] =>
class NetSuite\Classes\ItemSearchRow#2476 (23) {
public $basic =>
class NetSuite\Classes\ItemSearchRowBasic#2477 (322) {
public $accBookRevRecForecastRule =>
NULL
public $accountingBook =>
NULL
public $accountingBookAmortization =>
NULL
public $accountingBookCreatePlansOn =>
NULL
public $accountingBookRevRecRule =>
NULL
public $accountingBookRevRecSchedule =>
NULL
public $allowedShippingMethod =>
NULL
public $alternateDemandSourceItem =>
NULL
public $assetAccount =>
NULL
public $atpLeadTime =>
NULL
(more elements)...
}
public $assemblyItemBillOfMaterialsJoin =>
NULL
public $binNumberJoin =>
NULL
public $binOnHandJoin =>
NULL
public $correlatedItemJoin =>
NULL
public $effectiveRevisionJoin =>
NULL
public $fileJoin =>
NULL
public $inventoryDetailJoin =>
NULL
public $inventoryLocationJoin =>
NULL
public $inventoryNumberJoin =>
NULL
(more elements)...
}
}
}
}
}
After searching through the XML response from the server, it looks like Netsuite was responding with only the columns declared in my saved search as I wanted. The other null values I was receiving were initialized as default values when the response object was initialized.
I have the following issue. I have just created a new mongodb instance in my aws account with the same version but the results coming from my php queries come in a different way.
Before I used to get an array of objects but now I get and array of arrays.
For example :
Before:
array(1) {
[0] =>
class stdClass#401 (6) {
public $_id =>
class MongoDB\BSON\ObjectId#390 (1) {
public $oid =>
string(24) "5a685fa82fdc5d031e25451c"
}
}
}
Now:
array(1) {
[0]=>
object(stdClass)#393 (6) {
["_id"]=>
object(MongoDB\BSON\ObjectId)#390 (1) {
["oid"]=>
string(24) "5a685fa82fdc5d031e25451c"
}
}
}
Before I used to access my variables from php using the arrow like :
$document->_id;
but now, after getting the results in that way, I need to get change everything to :
$document['_id'];
Is there any setting (php/mongo server) so I can get the results like previously?
I use the php mongo driver to query my database - e.g :
$query = new Query($filter, $options);
/** #var MongoDB\Driver\Manager $manager */
return $manager->executeQuery($collection,$query)->toArray();
Thank you
In the cursor you can specify how it returns the results with setTypemap. I think ['document' => 'stdClass'] will do the trick:
$query = new Query($filter, $options);
/** #var MongoDB\Driver\Manager $manager */
$cursor = $manager->executeQuery($collection, $query);
$cursor->setTypeMap(['document' => 'stdClass']);
return $cursor->toArray();
$cursor->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
At the moment I test with this piece of code:
<?php
class Alert {
private $type;
private $message;
public static $_alerts = array();
public function add($type, $message) {
$this->type = $type;
$this->message = $message;
self::$_alerts[] = $this;
}
}
$alert = new Alert();
$alert->add("warning", "test 1");
$alert->add("error", "test 2");
echo "<pre>";
print_r(Alert::$_alerts);
echo "</pre>";
But my results are not like expected:
Array
(
[0] => Alert Object
(
[type:Alert:private] => error
[message:Alert:private] => test 2
)
[1] => Alert Object
(
[type:Alert:private] => error
[message:Alert:private] => test 2
)
)
Why is my added object changed?
Test area: http://codepad.viper-7.com/6q2H2A
That's because your object (i.e. $this in internal context) will be copied by reference, not by value. To do copy by value, you'll need to do:
public function add($type, $message)
{
$this->type = $type;
$this->message = $message;
self::$_alerts[] = clone $this;
}
As an alternative, you'll need to instantiate (that is, for example, constructions like new self - but clone seems to be more flexible here) your object as many times as you'll wish to copy.
By the way, there's easy way to realize what's going on. Use var_dump() instead of print_r() - then you'll see that objects are actually same. Sample for your code (i.e. where copying is not fixed yet):
array(2) {
[0]=>
object(Alert)#1 (2) {
["type":"Alert":private]=>
string(5) "error"
["message":"Alert":private]=>
string(6) "test 2"
}
[1]=>
object(Alert)#1 (2) {
["type":"Alert":private]=>
string(5) "error"
["message":"Alert":private]=>
string(6) "test 2"
}
}
-as you can see, objects are same there.
You save 2 refferences to the same object in your $_alerts array. You need to create a new object for each alert or do something like this:
<?php
class Alert {
private $type;
private $message;
public static $_alerts = array();
private function __construct($type,$message){
$this->type=$type;
$this->message = $message;
}
public function getMessage(){
return $this->message;
}
public function getType(){
return $this->type;
}
public static function add($type, $message) {
self::$_alerts[] = new self($type,$message);
}
}
Alert::add("warning", "test 1");
Alert::add("error", "test 2");
echo "<pre>";
print_r(Alert::$_alerts);
echo "</pre>";
The problem you are seeing is because your code is changing the same object twice.
The first call, it will set the data "warning" and "test 1", and the second time it will overwrite these values.
You can solve this by creating a new instance of the object and adding the data:
$alert = new Alert();
$alert->add("warning", "test 1");
$alert2 = new Alert();
$alert2->add("error", "test 2");
This should give the following result:
Array
(
[0] => Alert Object
(
[type:Alert:private] => warning
[message:Alert:private] => test 1
)
[1] => Alert Object
(
[type:Alert:private] => error
[message:Alert:private] => test 2
)
)
So I have in-app-billing working with PHP server verify. However, I cant figure out how to separate my signed data Strings into separate strings in PHP. When I echo $signedData in PHP I get the following.
{\"nonce\":4658477652655443541,\"orders\":[{\"notificationId\":\"android.test.purchased\",\"orderId\":\"transactionId.android.test.purchased\",\"packageName\":\"com.coolboy.coolapp\",\"productId\":\"android.test.purchased\",\"purchaseTime\":1350913071409,\"purchaseState\":0}]}
How do you separate the nonce, orders, and etc. in PHP to separate variables?
Thanks
Use json_decode to decode the string into an object.
This code:
$str = "{\"nonce\":4658477652655443541,\"orders\":[{\"notificationId\":\"android.test.purchased\",\"orderId\":\"transactionId.android.test.purchased\",\"packageName\":\"com.coolboy.coolapp\",\"productId\":\"android.test.purchased\",\"purchaseTime\":1350913071409,\"purchaseState\":0}]}";
$json = json_decode($str);
var_dump($json);
Produces:
class stdClass#1 (2) {
public $nonce =>
double(4.6584776526554E+18)
public $orders =>
array(1) {
[0] =>
class stdClass#2 (6) {
public $notificationId =>
string(22) "android.test.purchased"
public $orderId =>
string(36) "transactionId.android.test.purchased"
public $packageName =>
string(19) "com.coolboy.coolapp"
public $productId =>
string(22) "android.test.purchased"
public $purchaseTime =>
double(1350913071409)
public $purchaseState =>
int(0)
}
}
}
And of course you can do:
$nonce = $json->nonce;
$notificationId = $json->orders[0]->notificationId;
// etc...
More info on JSON:
http://en.wikipedia.org/wiki/JSON (less technical)
http://www.json.org/ (more technical)
That's JSON.
$array = json_decode($var);