Long Soap calls not getting returned value - php

I am trying to call a magento api method thanks to a php SoapClient object.
The problem is the method called creates magentos products and can be relatively long (up to 2 minutes). I need to get the returned values of this method but after a while, the soap call stops and return null.
$session_id = _get_session_id();
$client = new SoapClient($api_url . '&SID=' . $session_id, array('trace' => 1));
try {
$session = $client->login($api_user, $api_password);
$result = $client->call($session, 'api_call.method', array($arg1, $arg2);
}
catch(SoapFault $soapFault) {
...
}
I really need to get the called method return value, whatever the time it takes.
Do you know why the call return null after a while?
Is there a default timeout that can be configured?

Here is a solution, thanks to Jürgen comment:
ini_set('default_socket_timeout', 120); // 2 minutes
This set the call timeout to 2 minutes long

Related

PHP wait wait a variable is different from null

I'm looking for a way to wait my script until a variable is still different from null.Actually, I am submitting a batch job file and I need to wait until I get the id.
I took a look at sleep function, but it seems not matching to my need.
I need to do something like that:
<?php
...
$options = array('features' => SOAP_SINGLE_ELEMENT_ARRAYS);
$client = new SoapClient($URL, $options);
$result = $client->submitBatchJob(array('data'=>$data, 'process'=>$NameChecker))
->submitBatchJobResult;
while($result=='');
wait;
//execute rest of the php script...
?>
What you're looking for is:
if($variable === NULL) {...}
PHP treats NULL, false, 0, and the empty string as equal.

PHP 5X.X is sending zero as value to any SOAP service

I have a webservice with one one method that reurns an objetc, the method is very simple getObject(int id);
I made a PHP client to test it:
<?php
ini_set("soap.wsdl_cache_enabled", "1"); // Set to zero to avoid caching WSDL
$soapClient = new SoapClient('http://localhost:8080/ws-tickets/tickets2?wsdl');
$id = 2;
$result = $soapClient->get Ticket($id);
print_r($result);
?>
Well, I debug the WS when it is called by this php client and I see that the parameter received by it is ZERO.
If in my database I create a record that has "0" as id, the phpclient will retrieve it perfectly and every data is printed as it supouse to be for the print_r($result); command.
But, no mather wich parameter I send, it allways came to ZERO to the ws and I do not know what I am doing wrong
My Java WS is
#WebService
public class tickets2 {
#EJB
reciboDAO reciboDAO;
public ticket getTicket(int id){
recibo a = this.reciboDAO.getReciboporid(id);
return a;
}
}

Call to undefined method stdClass

I am occasionally getting the PHP Fatal error: Call to undefined method stdClass::transition() in agent.php on line 25 (I marked line 25 in the code). This code is called often, so struggling to see why it is happening.
Here is the snippet of agent.php that calls the
function agent_exam_complete($exam){
$ce = $exam->educational();
$ce->exam_id = $exam->exam_id;
$ce->exam_grade = $exam->score;
$ce->exams_remaining -= 1;
$ce->exam_received_date = sql_now();
if($exam->status()=='passed'){
$ce->transition('passed');
}elseif($ce->exams_remaining <= 0){
$ce->transition('failed');
}
$ce->save();
if($ce->is_certification_completed($ce->certification_id, $ce->client_no)){
agent_certification_complete($ce->certification_id, $ce->client_no);
}
}
function agent_certification_complete($certification_id, $client_no){
$ce = ClientPurchase::find('first', array('conditions' => "certification_id = '$certification_id' and is_certification = 1 and client_no='$client_no'"));
$ce->certification_date = date('Y-m-d');
$ce->transition('passed'); **//Line 25**
$ce->save();
}
transition() is defined in another file and is called often. I've included a little bit of it's code just for flavor.
function transition($event_tag){
$old_status = $this->status;
$next_status = $this->next_status_for_transition($event_tag);
if($next_status==''){
return; }
$this->status = $next_status;
My question is, why am I only getting this error periodically and not all the time? What can I do to eliminate the error and subsequent blank screen for my clients? I've only noticed that it is happening to those with Firefox or Chrome.
Thanks in advance,
Jim
The object $ce that contains the function is being generated multiple times. I suppose this is so transition is customized for whatever object is called.
Why not create another object for re-useable functions? Consider expanding the function so that it is compatible with all objects that would use it.
$my = new functionClass;
class functionClass
{
function transition()
{
$old_status = $this->status;
$next_status = $this->next_status_for_transition($event_tag);
if($next_status==''){
return; }
$this->status = $next_status;
}
}
$my->transition( 'passed' );
Something like that would cut down on unpredictability and I believe may solve your problem.
Try this little snippet of code to see whats going on:
$ce = false;
$ce->certification_date = date('Y-m-d');
var_dump($ce);
In this case $ce get cast to an object of stdClass when you try to set a property (certification_date).
Now your code:
function agent_certification_complete($certification_id, $client_no){
$ce = ClientPurchase::find('first', array('conditions' => "certification_id = '$certification_id' and is_certification = 1 and client_no='$client_no'"));
//$ce is probably false or null
//it gets cast to a stdClass object
$ce->certification_date = date('Y-m-d');
//stdClass does not have a transition method; ERROR
$ce->transition('passed'); **//Line 25**
$ce->save();
}
So in your code, if find() is returning null or false, or maybe some other choice values, $ce gets cast to a stdClass object on the next line. Then that stdClass object does not have a transition() method so you get an error.
To fix this, either adjust your find method or check its return value and handle accordingly.
As to it happening only in certain browser, I think thats a false conclusion. If find() is calling a query, it probably only happens at certain times depending on the result of that query.

How to reset a Mock Object with PHPUnit

How can I reset the expects() for a PHPUnit Mock?
I have a mock of the SoapClient that I would like to call multiple times within a test, resetting the expectations of each run.
$soapClientMock = $this->getMock('SoapClient', array('__soapCall'), array($this->config['wsdl']));
$this->Soap->client = $soapClientMock;
// call via query
$this->Soap->client->expects($this->once())
->method('__soapCall')
->with('someString', null, null)
->will($this->returnValue(true));
$result = $this->Soap->query('someString');
$this->assertFalse(!$result, 'Raw query returned false');
$source = ConnectionManager::create('test_soap', $this->config);
$model = ClassRegistry::init('ServiceModelTest');
// No parameters
$source->client = $soapClientMock;
$source->client->expects($this->once())
->method('__soapCall')
->with('someString', null, null)
->will($this->returnValue(true));
$result = $model->someString();
$this->assertFalse(!$result, 'someString returned false');
With a bit more of an investigation, it seems you just call expect() again.
However, the issue with the example is the usage of $this->once(). For the duration of the test, the counter associated with expects() can not be reset. To combat this, you have a couple of options.
The first option is to ignore the number of times it gets called with $this->any().
The second option is to target the call with the usage of $this->at($x). Remember that $this->at($x) is the number of times the mock object gets called, not the particular method, and starts at 0.
With my specific example, because the mock test is the same both times, and is only expected to be called twice, I can also use $this->exactly(), with only one expects() statement. i.e.
$soapClientMock = $this->getMock('SoapClient', array('__soapCall'), array($this->config['wsdl']));
$this->Soap->client = $soapClientMock;
// call via query
$this->Soap->client->expects($this->exactly(2))
->method('__soapCall')
->with('someString', null, null)
->will($this->returnValue(true));
$result = $this->Soap->query('someString');
$this->assertFalse(!$result, 'Raw query returned false');
$source = ConnectionManager::create('test_soap', $this->config);
$model = ClassRegistry::init('ServiceModelTest');
// No parameters
$source->client = $soapClientMock;
$result = $model->someString();
$this->assertFalse(!$result, 'someString returned false');
Kudos for this answer that assisted with $this->at() and $this->exactly()
You can clear mocks like this:
// Verify first
$mock->mockery_verify();
// and then overwrite with empty expectation directors
foreach(array_keys($mock->mockery_getExpectations()) as $method) {
$mock->mockery_setExpectationsFor($method, new Mockery\ExpectationDirector($method, $mock));
}

facebook api: count attendees for event (limit problem)

Okay normally I'm all fine about the facebook API but I'm having a problem which just keeps me wondering. (I think it's a bug (Check ticket http://bugs.developers.facebook.net/show_bug.cgi?id=13694) but I wanted to throw it here if somebody has an idea).
I'm usng the facebook PHP library to count all attendees for a specific event
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending');
this works without a problem it correctly returns an array with all attendees...
now heres the problem:
This event has about 18.000 attendees right now.
The api call returns a max number of 992 attendees (and not 18000 as it should).
I tried
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending?limit=20000');
for testing but it doesn't change anything.
So my actual question is:
If I can't get it to work by using the graph api what would be a good alternative? (Parsing the html of the event page maybe?) Right now I'm changing the value by hand every few hours which is tedious and unnecessary.
Actually there are two parameters, limit and offset. I think that you will have to play with both and continue making calls until one returns less than the max. limit.
Something like this, but in a recursive approach (I'm writting pseudo-code):
offset = 0;
maxLimit = 992;
totalAttendees = count(result)
if (totalAttendees >= maxLimit)
{
// do your stuff with each attendee
offset += totalAttendees;
// make a new call with the updated offset
// and check again
}
I've searched a lot and this is how I fixed it:
The requested URL should look something like this.
Here is where you can test it and here is the code I used:
function events_get_facebook_data($event_id) {
if (!$event_id) {
return false;
}
$token = klicango_friends_facebook_token();
if ($token) {
$parameters['access_token'] = $token;
$parameters['fields']= 'attending_count,invited_count';
$graph_url = url('https://graph.facebook.com/v2.2/' . $event_id , array('absolute' => TRUE, 'query' => $parameters));
$graph_result = drupal_http_request($graph_url, array(), 'GET');
if(is_object($graph_result) && !empty($graph_result->data)) {
$data = json_decode($graph_result->data);
$going = $data->attending_count;
$invited = $data->invited_count;
return array('going' => $going, 'invited' => $invited);
}
return false;
}
return false;
}
Try
SELECT eid , attending_count, unsure_count,all_members_count FROM event WHERE eid ="event"

Categories