サーチ…


RESTFul APIを使用する

REP(Representational State Transfer)は、Roy Fieldingが2000年に導入し定義したWeb開発に使用されるアーキテクチャスタイルです。

wikiで見る: REST wiki

HTTPプロトコル( Wiki上のHTTP)、HTTP要求(GET、POST、PATCH、DELETE ...)/応答コード(404,400,200,201,500 ...)およびボディ構造に基づいています。

これはあなたのデータをインターネット上の別のシステムに公開するのに最適です。

あなたのローカルデータベース上でStackOverFlower(User)を管理するためのRESTFul APIを作成したいとします。

例を作ろう!

Symfony 2.8フレームワーク

  1. Webサーバー:

ローカルマシンにWebサーバーをインストールして構成する必要があります.WampまたはLampまたはMampを参照してください。最新バージョンのPHPが必要ですSymfonyの要件!!!

  1. Php cliと作曲家:

あなたは私たちの友人のGoogleでこの "PHP cli [OS-NAME] how-to"をタイプして、PHP cli(システムによって異なる)を設定しなければなりません!あなたはコンポーザをインストールする必要があります。

  1. Symfony:

Symfony 2.8をインストールする必要があります(コンポーザー付き、より良い方法です)。端末(またはWindowsのcmd)を開き、Webサーバーのパスに移動します。

Symfony 2はより良い構造体型の一つであるバンドルと連携します。すべてはSymfonyのバンドルです!上記のテストができます。

cd /your-web-server-path/
composer create-project symfony/framework-standard-edition example "2.8.*"

Symfony 2.8が "example"ディレクトリにインストールされています。

  1. JMSSerializerバンドルのFOSRest(FriendsOfSymfony用):

次の2つのバンドルをインストールする必要があります。

JMSSerializer( インストール ):

composer require jms/serializer-bundle "~0.13"

FosRestBundle( インストール ):

composer require friendsofsymfony/rest-bundle

AppKernel.phpでそれらを有効にすることを忘れないでください!

  1. 基本設定:

独自の "Example"バンドルを作成し、データベースを作成します。

cd /path/to/your/symfony/
php app/console generate:bundle
php app/console doctrine:generate:database

Symfony 2.8アプリケーション設定ファイルの一番下に移動し、貼り付けます:

#app/config/config.yml
fos_rest:
    format_listener:
        rules:
            - { path: '^/stackoverflower', priorities: ['xml', 'json'], fallback_format: xml, prefer_extension: true }
            - { path: '^/', priorities: [ 'text/html', '*/*'], fallback_format: html, prefer_extension: true }

doctrineディレクトリ( "example / src / ExampleBundle / Entity")とリソースファイル( "StackOverFlower.orm.yml")を作成します。

# src/ExampleBundle/Resources/config/doctrine/StackOverFlower.orm.yml
ExampleBundle\Entity\StackOverFlower:
    type: entity
    table: stackoverflower
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 100

エンティティの生成とスキーマの更新:

php app/console doctrine:generate:entity StackOverFlower
php app/console doctrine:schema:update --force

デフォルトコントローラを作成する:

#src/ExampleBundle/Controller/StackOverFlowerController.php

namespace ExampleBundle\Controller;

use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Request;

use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\Delete;

use ExampleBundle\Entity\StackOverFlower;

class StackOverFlowerController extends FOSRestController
{
    /**
     * findStackOverFlowerByRequest
     * 
     * @param Request $request
     * @return StackOverFlower
     * @throws NotFoundException
     */
    private function findStackOverFlowerByRequest(Request $request) {
        
        $id = $request->get('id');
        $user = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:StackOverFlower")->findOneBy(array('id' => $id));
        
        return $user;
    }
    
    /**
     * validateAndPersistEntity
     * 
     * @param StackOverFlower $user
     * @param Boolean $delete
     * @return View the view
     */
    private function validateAndPersistEntity(StackOverFlower $user, $delete = false) {
        
        $template = "ExampleBundle:StackOverFlower:example.html.twig";
        
        $validator = $this->get('validator');
        $errors_list = $validator->validate($user); 
        
        if (count($errors_list) == 0) {
            
            $em = $this->getDoctrine()->getManager();
            
            if ($delete === true) {
                $em->remove($user);
            } else {
                $em->persist($user);
            }
            
            $em->flush();
            
            $view = $this->view($user)
                         ->setTemplateVar('user')
                         ->setTemplate($template);
        } else {
            
            $errors = "";
            foreach ($errors_list as $error) {
                $errors .= (string) $error->getMessage();  
            }
            
            $view = $this->view($errors)
                         ->setTemplateVar('errors')
                         ->setTemplate($template);
            
        } 
        
        return $view;
    }
    
    /**
     * newStackOverFlowerAction
     * 
     * @Get("/stackoverflower/new/{name}")
     * 
     * @param Request $request
     * @return String
     */
    public function newStackOverFlowerAction(Request $request)
    {   
        $user = new StackOverFlower();
        $user->setName($request->get('name'));
        
        $view = $this->validateAndPersistEntity($user);
            
        return $this->handleView($view);
    }
      
    /**
     * editStackOverFlowerAction
     * 
     * @Get("/stackoverflower/edit/{id}/{name}")
     * 
     * @param Request $request
     * @return type
     */
    public function editStackOverFlowerAction(Request $request) {
        
        $user = $this->findStackOverFlowerByRequest($request);
        
        if (! $user) {
            $view = $this->view("No StackOverFlower found for this id:". $request->get('id'), 404);
            return $this->handleView($view);
        }
        
        $user->setName($request->get('name'));
        
        $view = $this->validateAndPersistEntity($user);
                
        return $this->handleView($view);
    }
    
    /**
     * deleteStackOverFlowerAction
     * 
     * @Get("/stackoverflower/delete/{id}")
     * 
     * @param Request $request
     * @return type
     */
    public function deleteStackOverFlowerAction(Request $request) {
        
        $user = $this->findStackOverFlowerByRequest($request);
        
        if (! $user) {
            $view = $this->view("No StackOverFlower found for this id:". $request->get('id'), 404);
            return $this->handleView();
        }
        
        $view = $this->validateAndPersistEntity($user, true);
                
        return $this->handleView($view);
    }
    
    /**
     * getStackOverFlowerAction
     * 
     * @Get("/stackoverflowers")
     * 
     * @param Request $request
     * @return type
     */
    public function getStackOverFlowerAction(Request $request) {
        
        $template = "ExampleBundle:StackOverFlower:example.html.twig";
        
        $users = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:StackOverFlower")->findAll();
        
        if (count($users) === 0) {
            $view = $this->view("No StackOverFlower found.", 404);
            return $this->handleView();
        }
        
        $view = $this->view($users)
                     ->setTemplateVar('users')
                     ->setTemplate($template);
        
        return $this->handleView($view);
    }
}

デフォルトのTwigビューを作成する:

#src/ExampleBundle/Resources/views/StackOverFlower.html.twig
{% if errors is defined %}
  {{ errors }}  
{% else %}
  {% if users is defined %}
    {{ users | serialize }}
  {% else %}
    {{ user | serialize }}
  {% endif %}
{% endif %}

あなたはあなたの最初のRESTFul APIを作ったばかりです!

あなたはhttp://your-server-name/your-symfony-path/app_dev.php/stackoverflower/new/testでそれをテストすることができます。

あなたがデータベースで見ることができるように、 "test"という名前の新しいユーザーが作成されました。

stackoverflowerのリストは、 http://your-server-name/your-symfony-path/app_dev.php/stackoverflowersで取得できます。

この例の私のgithubアカウントの完全な例があります: Git Hubの例 、この例の "master"ブランチ、さらに "real-routes"ブランチの例(POSTやDELETEなど)

後でSOAPで例を見てください!

宜しくお願いします、

マチュー

SOAP APIを使用する

SOAP(Simple Access Object Protocol)はXML-RPCのようにXMLベースのもので、 祖先であり 、公開されるメソッドを記述するWSDLというファイルがあります。

このプロトコルは、多くの場合SOAP-EnveloppeSOAP-Body 、およびSOAP-Headerに基づいています。データは構造内にエンベロープされ、異なる言語から同じ方法で解釈されます。

SOAPメッセージの説明

詳細は、以下を参照してください: SOAP on wiki

上で説明したように、Webサービスを記述するために最も重要なのはWSDLファイルです。以下を参照してください。WSDL on wiki

この作業の基本は、SOAP APIに公開されているものを定義することです。クラスとビジネスプロセスは、基本的なPHP SOAPServerクラスによって自動的に処理されます。あなたはまだコードが必要です!

ファイルの構築方法を見てみましょう:

  1. サービス:API URIと関連するものを設定します。
  2. バインディング:サービスに関連する操作を定義します。
  3. 操作:Webに公開するいくつかのメソッド
  4. PortTypes:クエリと応答を定義する
  5. リクエストとレスポンス:入力と出力を期待するもの
  6. メッセージ:各IO上でどのようなformt(パラメータ)が必要なのかは、単純なもの(文字列、整数、浮動小数点数)または複合型(構造化形式)

この基本情報を使用すると、必要なすべてのAPIを実現できます。

あなたのローカルデータベース上であなたのStackOverFlower(User)を管理するSOAP APIを作ろうとしているとします。

例を作ろう!

Webサーバー、Php cli、Composer、Symfony 2.8をインストールし、新しいバンドル "ExampleBundle"を作成し、上記のようなスキーマを構築します。

ビジネスロジックの構築を開始する前に、コントローラの公開対象を知る必要がありました。このジョブは、WSDLを使用して実行されます。これは、WSDLの優れた構文の例です。

<definitions name="StackOverFlowerService"
   targetNamespace="http://example/soap/stackoverflower.wsdl"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns="http://example/soap/stackoverflower.wsdl"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
   <message name="NewRequest">
      <part name="name" type="xsd:string"/>
   </message>
    
   <message name="NewResponse">
      <part name="status" type="xsd:string"/>
   </message>

   <message name="getListRequest"></message>
    
   <message name="getListResponse">
      <part name="list" type="xsd:string"/>
   </message>

   <message name="editRequest">
      <part name="id" type="xsd:string"/>
      <part name="name" type="xsd:string"/>
   </message>
    
   <message name="editResponse">
      <part name="status" type="xsd:string"/>
   </message>
   
   <message name="deleteRequest">
      <part name="id" type="xsd:string"/>
   </message>
    
   <message name="deleteResponse">
      <part name="status" type="xsd:string"/>
   </message>
   
   <portType name="StackOverFlower_PortType">
      <operation name="newStack">
         <input message="tns:NewRequest"/>
         <output message="tns:NewResponse"/>
      </operation>
      <operation name="getList">
         <input message="tns:getListRequest"/>
         <output message="tns:getListResponse"/>
      </operation>
      <operation name="edit">
         <input message="tns:editRequest"/>
         <output message="tns:editResponse"/>
      </operation>
      <operation name="delete">
         <input message="tns:deleteRequest"/>
         <output message="tns:deleteResponse"/>
      </operation>
   </portType>

   <binding name="StackOverFlower_Binding" type="tns:StackOverFlower_PortType">
      <soap:binding style="rpc"
         transport="http://schemas.xmlsoap.org/soap/http"/>
      <operation name="newStack">
         <soap:operation soapAction="newStack"/>
         <input>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:new"
               use="encoded"/>
         </input>
        
         <output>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:new"
               use="encoded"/>
         </output>
      </operation>
      
      <operation name="getList">
         <soap:operation soapAction="getList"/>
         <input>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:get-list"
               use="encoded"/>
         </input>
        
         <output>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:get-list"
               use="encoded"/>
         </output>
      </operation>
      
      <operation name="edit">
         <soap:operation soapAction="edit"/>
         <input>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:edit"
               use="encoded"/>
         </input>
        
         <output>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:edit"
               use="encoded"/>
         </output>
      </operation>
      
      <operation name="delete">
         <soap:operation soapAction="delete"/>
         <input>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:delete"
               use="encoded"/>
         </input>
        
         <output>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:example:delete"
               use="encoded"/>
         </output>
      </operation>
   </binding>

   <service name="StackOverFlower_Service">
      <documentation>Description File of StackOverFlowerService</documentation>
      <port binding="tns:StackOverFlower_Binding" name="StackOverFlower_Port">
         <soap:address
            location="http://example/stackoverflower/" />
      </port>
   </service>
</definitions>

これをあなたのweb symfonyディレクトリ(soapサブディレクトリにあり、これを "stackoverflower.wsdl"と名づけてください)で取得する必要があります。

本当にWSD1の例から触発されましたオンラインWSDl検証ツールで検証することができます

その後、 SOAP Symfony 2.8 Docからインスピレーションを受けた基本的なサービスとコントローラを作成することができます。

PHP SOAPServerによって処理されるサービス:

#src\ExampleBundle\Services\StackOverFlowerService.php
namespace ExampleBundle\Services;

use Doctrine\ORM\EntityManager;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

use ExampleBundle\Entity\StackOverFlower;

class StackOverFlowerService
{
  private $em;
  private $stackoverflower;

  public function __construct(EntityManager $em)
  {
    $this->em = $em;
  }

  public function newStack($name)
  {
    $stackoverflower = new StackOverFlower();
    $stackoverflower->setName($name);
    
    $this->em->persist($stackoverflower);
    $this->em->flush();
    
    return "ok";
  }
  
  public function getList()
  {
    $stackoverflowers = $this->em->getRepository("ExampleBundle:StackOverFlower")->findAll();
    
    $encoders = array(new XmlEncoder(), new JsonEncoder());
    $normalizers = array(new ObjectNormalizer());

    $serializer = new Serializer($normalizers, $encoders);
    
    return $serializer->serialize($stackoverflowers, 'json');
  }
  
  public function edit($id, $name)
  {
    $stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")->findOneById($id);
    
    $stackoverflower->setName($name);
    
    $this->em->persist($stackoverflower);
    $this->em->flush();
    
    return "ok";
  }
    
  public function delete($id)
  {
    $stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")->findOneById($id);
    
    $this->em->remove($stackoverflower);
    $this->em->flush();
    
    return "ok";
  }
}

このサービスを設定します:

#src\ExampleBundle\Resources\config\services.yml
services:
  stackoverflower_service:
    class: ExampleBundle\Services\StackOverFlowerService
    arguments: [@doctrine.orm.entity_manager]

ご覧のとおり、Doctrine Entity MangerをCRUD StackOverFlower Objectに使用する必要があるため、依存関係として注入します。

コントローラ、サービスオブジェクトを公開する:

#src\ExampleBundle\Controller\StackOverFlowerController.php
namespace ExampleBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class StackOverFlowerController extends Controller
{
  public function indexAction()
  {
    ini_set("soap.wsdl_cache_enabled", "0");

    $options = array(
      'uri' => 'http://example/app_dev.php/soap',
      'cache_wsdl' => WSDL_CACHE_NONE, 
      'exceptions' => true
    );
  
    $server = new \SoapServer(dirname(__FILE__).'/../../../**web/soap/stackoverflower.wsdl**', $options);
    $server->setObject($this->get('stackoverflower_service'));

    $response = new Response();
    $response->headers->set('Content-Type', 'text/xml; charset=utf-8');

    ob_start();
    $server->handle();
    $response->setContent(ob_get_clean());

    return $response;
  }
}

サービスの詳細については、以下を参照してください: Symfony docのサービスコンテナ

ルート :

example_soap:
  path:     /soap
  defaults: { _controller: ExampleBundle:StackOverFlower:index }

基本的なTwigテンプレート:

#src\ExampleBundle\Resources\views\Soap\default.html.twig
{% if status is defined %}
{{ status }}
{% else %}
{{ list }}
{% endif %}

Symfony 2.8で最初のSOAP APIを作ったのです!

あなたがそれを公開する前に、我々はテストする必要があります!

あなたのStackOverFlowerControllerに、これを追加します:

  public function testNewAction(Request $request)
  {
    $service = $this->get('stackoverflower_service');
    $result = $service->newStack($request->query->get('name'));
    
    return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result));
  }
  
  public function testEditAction(Request $request)
  {
    $service = $this->get('stackoverflower_service');
    $result = $service->edit($request->query->get('id'), $request->query->get('name'));
    
    return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result));
  }
  
  public function testGetListAction(Request $request)
  {
    $service = $this->get('stackoverflower_service');
    $result = $service->getList();
    
    return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result));
  }
  
  public function testDeleteAction(Request $request)
  {
    $service = $this->get('stackoverflower_service');
    $result = $service->delete($request->query->get('id'));
    
    return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result));
  }

// To test this from an another server, you can type this :
// $client = new \SoapClient("http://example/app_dev.php/soap?wsdl", array("trace" => 1, "exception" => 1)); 
// $result = $client->newStack($request->query->get('name'));
// print_r($result); 

ルート:

test_new:
  path:     /stackoverflower/new
  defaults: { _controller: ExampleBundle:StackOverFlower:testNew }
  
test_edit:
  path:     /stackoverflower/edit
  defaults: { _controller: ExampleBundle:StackOverFlower:testEdit }
  
test_get_list:
  path:     /stackoverflower/get-list
  defaults: { _controller: ExampleBundle:StackOverFlower:testGetList }
  
test_delete:
  path:     /stackoverflower/delete
  defaults: { _controller: ExampleBundle:StackOverFlower:testDelete }

ブラウザでこれを入力できます:

  1. getList
  2. 新しい
  3. 編集
  4. 削除

これはSOAPを使用した非セキュアなAPIの非常に基本的な例ですが、あとでAPIのキー認証の背後にある安全な例の例を行うことができます。

そのすべての人々...

マチュー



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow