PHP早期发送SOAP响应?

时间:2010-06-28 15:26:45

标签: php xml soap salesforce flush

这是我一直在处理的一个老问题,但仍然没有解决方案,所以尝试新方法。

如何尽早发送SOAP响应(在脚本执行结束之前)?

如果在30秒之前未发送ACK文件,则会导致这些问题,因为此过程需要更长时间才能完成,然后才能完成分配时间。

flush()无效,得到此错误:

org.xml.sax.SAXParseException:XML文档结构必须在同一实体内开始和结束。

没有flush()我得到了这个

org.xml.sax.SAXParseException:文件过早结束。

脚本进程可能需要180秒才能完成,等待响应的服务器只会在超时前等待大约30秒(导致上述错误)。

关于我如何解决这个问题的任何想法?

以下是一些代码:这是我接受并发送即将发送的SOAP请求的ACK文件的方式

$data = 'php://input';
$content = file_get_contents($data);

if($content) {
    respond('true');
} else {
    respond('false');
}

回复功能

function respond($tf) {
    $ACK = <<<ACK
<?xml version = "1.0" encoding = "utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <notifications xmlns="http://soap.sforce.com/2005/09/outbound">
            <Ack>$tf</Ack>
        </notifications>
    </soapenv:Body>
</soapenv:Envelope>
ACK;

    print trim($ACK); 
}

PHP使用单线程处理方法,并且在线程完成处理之前不会发回ACK文件。在ACK提交后是否有某种方法可以关闭套接字并继续处理,因此我不会在发送服务器上出现这些超时问题?

2 个答案:

答案 0 :(得分:1)

a)(可选)您可以使用set_time_limit()来增加执行时间的时间限制。

b)您必须增加wsdl客户端对象的时间,例如:

$clientwsdl->setOpt('timeout', 300); // if you are using PEAR:SOAP.

大多数wsdl类允许定义超时。

c)而不是,你不能尽早使用SOAP,而不是至少使用一个调用。考虑到SOAP返回一个XML,因此部分XML通常是无效的(它会错过结束标记)。

d)替代,您可以使用除SOAP之外的其他方法,例如阅读网址:

$fp=fopen("http://www.mysite.com/url.php","r");

其中url.php返回列(或某种值而不使用xml:

30|50|70|80|20 
30|50|70|80|20
30|50|70|80|20

答案 1 :(得分:1)

据我所知,我们无法对30秒的限制做任何事情,并且在脚本完成之前不会刷新输出。你能尝试将你的处理逻辑分成两部分吗?

  1. “监听器”脚本,接受消息,记录要完成的作业并立即发送ACK,然后退出。
  2. 您身边的实际处理可能需要更长时间。
  3. “要完成的工作”可能是一个新生成的过程(查看pcntl_fork()函数的注释,但对我来说看起来不太有希望)或某种方式将数据存储在文件中或数据库并定期用另一个脚本处理它,例如计划每5分钟运行一次?

    如果60秒会以某种方式拯救你,你可以将你的出站信息重写为Apex的标注。基本上,您然后编写自己的SOAP信封并将其发送到任何http地址。你可以把它放在一个触发器中。有关此方法的限制,请参阅here


    其他咆哮:

    1. 我不认为您的确认对销售人员来说真的“重要”。出站邮件只是通知。您是否依赖Ack = true / false的应用程序中的其他位置?如果不是 - 盲目发送ack = true&amp;安排工作可能真的是要走的路;)
    2. 从另一个问题我理解你基本上只需要将更新存储在DB中。你意识到你不应该使用OM进行审计,对吧? (Link,搜索“审核”)。
    3. 让PHP成为活跃的一方会不会更简单?让它查询Salesforce [SELECT Id,Name FROM Account WHERE LastModifiedDate&gt; :lastTimeYouQueried]?这样你就可以把你想要的所有时间都用来处理结果:)