<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.yar.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'zh',
  ),
  'this' => 
  array (
    0 => 'yar.examples.php',
    1 => '示例',
    2 => '示例',
  ),
  'up' => 
  array (
    0 => 'book.yar.php',
    1 => 'Yar',
  ),
  'prev' => 
  array (
    0 => 'yar.constants.php',
    1 => '预定义常量',
  ),
  'next' => 
  array (
    0 => 'class.yar-server.php',
    1 => 'Yar_Server',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'zh',
    'path' => 'reference/yar/examples.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="yar.examples" class="chapter">
 <h1 class="title">示例</h1>

 <p class="simpara">
  下面的示例演示了一个完整的服务：一个暴露若干算术方法的服务端、
  一个调用它们的同步客户端、一个一次性发出多个并发调用的客户端，
  以及一个通过 TCP 与服务器通信的客户端。
 </p>

 <div class="example" id="example-1">
  <p><strong>示例 #1 Yar 服务端示例</strong></p>
  <div class="example-contents"><p>
   Yar 服务就是一个由 <span class="classname"><a href="class.yar-server.php" class="classname">Yar_Server</a></span>
   包装的普通 PHP 类。对象的每一个公开方法都会成为一个 RPC
   端点，而受保护方法、私有方法以及方法名以下划线开头的方法，
   对客户端不可见。公开方法的文档注释会被收集起来，
   显示在服务信息页面上。
  </p></div>
  <div class="example-contents"><p>
   RPC 请求以 HTTP POST 请求的形式到达，请求体携带 Yar 二进制协议
   负载，因此这个脚本通常被映射为常规 Web 服务器上的一个 URI。
  </p></div>
  <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php

</span><span style="color: #FF8000">/* 假设这个页面可以通过 http://api.example.com/operator.php 访问 */

</span><span style="color: #007700">class </span><span style="color: #0000BB">Operator </span><span style="color: #007700">{

    </span><span style="color: #FF8000">/**
     * Add two operands
     * @param integer
     * @return integer
     */
    </span><span style="color: #007700">public function </span><span style="color: #0000BB">add</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">) {
        return </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_add</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">);
    }

    </span><span style="color: #FF8000">/**
     * Sub
     */
    </span><span style="color: #007700">public function </span><span style="color: #0000BB">sub</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">) {
        return </span><span style="color: #0000BB">$a </span><span style="color: #007700">- </span><span style="color: #0000BB">$b</span><span style="color: #007700">;
    }

    </span><span style="color: #FF8000">/**
     * Mul
     */
    </span><span style="color: #007700">public function </span><span style="color: #0000BB">mul</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">) {
        return </span><span style="color: #0000BB">$a </span><span style="color: #007700">* </span><span style="color: #0000BB">$b</span><span style="color: #007700">;
    }

    </span><span style="color: #FF8000">/**
     * Protected methods will not be exposed
     * @param integer
     * @return integer
     */
    </span><span style="color: #007700">protected function </span><span style="color: #0000BB">_add</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">) {
        return </span><span style="color: #0000BB">$a </span><span style="color: #007700">+ </span><span style="color: #0000BB">$b</span><span style="color: #007700">;
    }
}

</span><span style="color: #0000BB">$server </span><span style="color: #007700">= new </span><span style="color: #0000BB">Yar_Server</span><span style="color: #007700">(new </span><span style="color: #0000BB">Operator</span><span style="color: #007700">());
</span><span style="color: #0000BB">$server</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">handle</span><span style="color: #007700">();
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
  </div>

 </div>

 <div class="example" id="example-2">
  <p><strong>示例 #2 通过浏览器访问服务端（GET 请求）</strong></p>
  <div class="example-contents"><p>
   当向服务地址发起 GET 请求时（例如直接在浏览器中打开它），
   Yar 不会执行 RPC 调用，而是渲染一个信息页面，
   列出执行对象的每一个公开方法及其文档注释。
   该行为由
   <a href="yar.configuration.php#ini.yar.expose-info" class="link">yar.expose_info</a>
   配置项控制；当它关闭时，GET 请求将失败。
  </p></div>
  <div class="example-contents"><p>以上示例的输出类似于：</p></div>
  <div class="mediaobject">
   
   <div class="imageobject">
    <img src="images/4fd86c7f1b197d1d954ad0f4b033dc93-yar.png" alt="Yar Server Info" width="700px"  />
   </div>
  </div>
 </div>

 <div class="example" id="example-3">
  <p><strong>示例 #3 Yar 客户端示例</strong></p>
  <div class="example-contents"><p>
   <span class="classname"><a href="class.yar-client.php" class="classname">Yar_Client</a></span> 绑定到单一的服务地址。
   在它上面调用任何未定义的方法，都会被透明地转换为同步
   RPC 调用，远程方法用起来和本地方法一样；
   <span class="methodname"><a href="yar-client.call.php" class="methodname">Yar_Client::call()</a></span>
   显式地按方法名做同样的事情。
  </p></div>
  <div class="example-contents"><p>
   受保护方法不会被暴露：调用它们会失败，并抛出错误码为
   <strong><code><a href="yar.constants.php#constant.yar-err-request">YAR_ERR_REQUEST</a></code></strong> 的
   <span class="exceptionname"><a href="class.yar-client-exception.php" class="exceptionname">Yar_Client_Exception</a></span>。
  </p></div>
  <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
$client </span><span style="color: #007700">= new </span><span style="color: #0000BB">Yar_Client</span><span style="color: #007700">(</span><span style="color: #DD0000">"http://api.example.com/operator.php"</span><span style="color: #007700">);

</span><span style="color: #FF8000">/* 直接调用 */
</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$client</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">add</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">));

</span><span style="color: #FF8000">/* 通过 call() 调用 */
</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$client</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">call</span><span style="color: #007700">(</span><span style="color: #DD0000">"add"</span><span style="color: #007700">, array(</span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">)));

</span><span style="color: #FF8000">/* _add 无法被调用：它不是公开方法 */
</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$client</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_add</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">));
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
  </div>

  <div class="example-contents"><p>以上示例的输出类似于：</p></div>
  <div class="example-contents screen">
<div class="cdata"><pre>
int(3)
int(5)
PHP Fatal error:  Uncaught Yar_Client_Exception: call to undefined api Operator::_add() in *
</pre></div>
  </div>
 </div>

 <div class="example" id="example-4">
  <p><strong>示例 #4 Yar 并发客户端示例</strong></p>
  <div class="example-contents"><p>
   <span class="classname"><a href="class.yar-concurrent-client.php" class="classname">Yar_Concurrent_Client</a></span>
   不是逐个调用服务，而是先注册多个调用，然后通过
   <span class="methodname"><a href="yar-concurrent-client.loop.php" class="methodname">Yar_Concurrent_Client::loop()</a></span>
   一次性发出所有调用。响应按到达的顺序传递给回调函数，
   而不是按调用注册的顺序。
  </p></div>
  <div class="example-contents"><p>
   在全部请求发送完毕后，回调函数会以 <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong>
   参数被调用一次，以便调用方知道没有更多请求等待发送；
   下面的示例检查了这个通知。
  </p></div>
  <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
</span><span style="color: #007700">function </span><span style="color: #0000BB">callback</span><span style="color: #007700">(</span><span style="color: #0000BB">$ret</span><span style="color: #007700">, </span><span style="color: #0000BB">$callinfo</span><span style="color: #007700">) {
    if (</span><span style="color: #0000BB">$callinfo </span><span style="color: #007700">== </span><span style="color: #0000BB">NULL</span><span style="color: #007700">) {
        </span><span style="color: #FF8000">/* all requests are sent, waiting for the responses */
        </span><span style="color: #007700">return;
    }
    echo </span><span style="color: #0000BB">$callinfo</span><span style="color: #007700">[</span><span style="color: #DD0000">'method'</span><span style="color: #007700">], </span><span style="color: #DD0000">" result: "</span><span style="color: #007700">, </span><span style="color: #0000BB">$ret</span><span style="color: #007700">, </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;
}

function </span><span style="color: #0000BB">error_callback</span><span style="color: #007700">(</span><span style="color: #0000BB">$type</span><span style="color: #007700">, </span><span style="color: #0000BB">$error</span><span style="color: #007700">, </span><span style="color: #0000BB">$callinfo</span><span style="color: #007700">) {
    </span><span style="color: #0000BB">error_log</span><span style="color: #007700">(</span><span style="color: #DD0000">"[</span><span style="color: #0000BB">$type</span><span style="color: #DD0000">] </span><span style="color: #0000BB">$error</span><span style="color: #DD0000">"</span><span style="color: #007700">);
}

</span><span style="color: #FF8000">/* 注册对远程服务的异步调用 */
</span><span style="color: #0000BB">Yar_Concurrent_Client</span><span style="color: #007700">::</span><span style="color: #0000BB">call</span><span style="color: #007700">(</span><span style="color: #DD0000">"http://api.example.com/operator.php"</span><span style="color: #007700">, </span><span style="color: #DD0000">"add"</span><span style="color: #007700">, array(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">), </span><span style="color: #DD0000">"callback"</span><span style="color: #007700">);
</span><span style="color: #0000BB">Yar_Concurrent_Client</span><span style="color: #007700">::</span><span style="color: #0000BB">call</span><span style="color: #007700">(</span><span style="color: #DD0000">"http://api.example.com/operator.php"</span><span style="color: #007700">, </span><span style="color: #DD0000">"sub"</span><span style="color: #007700">, array(</span><span style="color: #0000BB">2</span><span style="color: #007700">, </span><span style="color: #0000BB">1</span><span style="color: #007700">), </span><span style="color: #DD0000">"callback"</span><span style="color: #007700">);
</span><span style="color: #0000BB">Yar_Concurrent_Client</span><span style="color: #007700">::</span><span style="color: #0000BB">call</span><span style="color: #007700">(</span><span style="color: #DD0000">"http://api.example.com/operator.php"</span><span style="color: #007700">, </span><span style="color: #DD0000">"mul"</span><span style="color: #007700">, array(</span><span style="color: #0000BB">2</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">), </span><span style="color: #DD0000">"callback"</span><span style="color: #007700">);

</span><span style="color: #FF8000">/* 发送所有请求并等待响应 */
</span><span style="color: #0000BB">Yar_Concurrent_Client</span><span style="color: #007700">::</span><span style="color: #0000BB">loop</span><span style="color: #007700">(</span><span style="color: #DD0000">"callback"</span><span style="color: #007700">, </span><span style="color: #DD0000">"error_callback"</span><span style="color: #007700">);
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
  </div>

  <div class="example-contents"><p>以上示例的输出类似于：</p></div>
  <div class="example-contents screen">
<div class="cdata"><pre>
mul result: 4
sub result: 1
add result: 3
</pre></div>
  </div>
 </div>

 <div class="example" id="example-5">
  <p><strong>示例 #5 Yar TCP 客户端示例</strong></p>
  <div class="example-contents"><p>
   除了 HTTP 之外，<span class="classname"><a href="class.yar-client.php" class="classname">Yar_Client</a></span> 还可以
   通过 TCP 或 Unix socket 与兼容 Yar 协议的服务器通信，
   例如一个由
   <a href="https://github.com/laruence/yar-c" class="link external">&raquo;&nbsp;Yar C 框架</a>
   实现的服务，它提供的二进制 Yar 协议与 PHP 服务端使用的相同。
  </p></div>
  <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php
$client </span><span style="color: #007700">= new </span><span style="color: #0000BB">Yar_Client</span><span style="color: #007700">(</span><span style="color: #DD0000">"tcp://127.0.0.1:8600"</span><span style="color: #007700">);

</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$client</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">add</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">));
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
  </div>

 </div>

</div>
<?php manual_footer($setup); ?>