수색…


RESTFul API 사용

REST (Representational State Transfer)는 Roy Fielding이 2000 년에 도입하고 정의한 웹 개발에 사용되는 아키텍처 스타일입니다.

wiki에서보기 : REST 위키

HTTP 프로토콜 ( Wiki의 HTTP ), HTTP 요청 (GET, POST, PATCH, DELETE ...) / 응답 코드 (404, 400, 200, 201, 500 ...) 및 본문 구조를 기반으로합니다.

이것은 인터넷상의 다른 시스템에 데이터를 노출시키는 좋은 방법입니다.

로컬 데이터베이스에서 StackOverFlower (User)를 관리하기 위해 RESTFul API를 만들고 싶다고 가정 해보십시오.

예제를 만들어 보겠습니다!

Symfony 2.8 프레임 워크

  1. 웹 서버 :

로컬 컴퓨터에 웹 서버를 설치하고 구성해야합니다. Wamp 또는 Lamp 또는 Mamp : 최신 버전의 PHP가 있어야합니다 ( Symfony 요구 사항 !!! ).

  1. PHP cli 및 작곡가 :

PHP cli (시스템마다 다를 수 있음)를 구성하고, Google의 친구 인 Google에서이 "PHP cli [OS-NAME] 사용법"을 입력하십시오! 작곡가를 설치하고 , 작곡가 설치를 참조하십시오.

  1. Symfony :

Symfony 2.8 (작곡가와 함께, 더 좋은 방법)을 설치해야하고, 터미널 (또는 Windows에서는 cmd)을 열고 웹 서버 경로로 가야합니다.

Symfony 2는 더 나은 구조 유형 중 하나 인 Bundles와 함께 작동합니다. 모두 Symfony의 번들입니다! 위에서 테스트 할 수 있습니다.

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

Symfony 2.8이 "example"디렉토리에 설치되었습니다.

  1. JMSSerializer 번들의 FOSRest (FriendsOfSymfony 용) :

다음 두 번들을 설치해야합니다.

JMSSerializer ( 설치 ) :

composer require jms/serializer-bundle "~0.13"

FosRestBundle ( 설치 ) :

composer require friendsofsymfony/rest-bundle

AppKernel.php에서 활성화하는 것을 잊지 마십시오!

  1. 기본 구성 :

자신의 "예제"번들을 만들고 데이터베이스를 만듭니다.

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 }

교리 디렉토리 ( "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);
    }
}

기본 나뭇 가지보기를 만듭니다.

#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"라는 이름으로 새 사용자가 생성되었습니다.

http : //your-server-name/your-symfony-path/app_dev.php/stackoverflowers 에서 stackoverflower의 목록을 가져올 수 있습니다 .

이 예제의 github 계정에 대한 전체 예제가 있습니다. Git Hub 예제 , "master"브랜치는이 예제, "real-routes"브랜치는 적절한 URL (예 : POST 및 DELETE) 예제입니다.

나중에 SOAP로 예제를 보자!

친애하는,

마티유

SOAP API 사용

SOAP (Simple Access Object Protocol)는 XML-RPC와 마찬가지로 XML 기반의 조상 이며, WSDL 이라는 파일이 있으며 노출 될 메소드를 설명합니다.

이 프로토콜은 종종 SOAP-Enveloppe , SOAP-BodySOAP-Header를 기반으로 하며, 데이터는 구조에 포함되어 다른 언어에서 동일한 방식으로 해석됩니다.

비누 메시지에 대한 설명

자세한 내용은 다음을 참조하십시오. Wiki의 SOAP

위에서 설명한 것처럼 웹 서비스를 설명하는 데 가장 중요한 것은 WSDL 파일입니다. WSDL에 대한 설명

기본 작업은 SOAP API에 노출되는 것을 정의하는 것이며, 클래스는 비즈니스 프로세스가 기본 PHP SOAPServer 클래스에 의해 자동으로 처리됩니다. 당신은 여전히 ​​코드가 필요합니다!

파일이 어떻게 생성되는지 보자.

  1. 서비스 : API URI와 관련 항목을 설정합니다.
  2. 바인딩 : 서비스와 관련된 작업을 정의합니다.
  3. 작업 : 웹에 공개 할 몇 가지 방법
  4. PortTypes : 쿼리 및 응답 정의
  5. 요청 및 응답 : 입력 및 출력 예상
  6. 메시지 : 각 IO에 대해 기대하는 formt (형식)은 단순 할 수 있습니다 (문자열, 정수, 부동 ...) 또는 복잡한 유형 (구조화 된 형식)

이 기본 정보를 사용하여 원하는 모든 API를 얻을 수 있습니다.

로컬 API에서 StackOverFlower (User)를 관리하기위한 SOAP API를 만들고 싶다고 가정 해보십시오.

예제를 만들어 보겠습니다!

웹 서버, 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>

우리는 이것을 symfony 디렉토리 (soap 서브 디렉토리에서 "stackoverflower.wsdl"이라고 부름)에서 가져와야합니다.

WSDl 예제 에서 실제로 영감을 얻었습니다. 온라인 WSDl Validator로 유효성을 검사 할 수 있습니다.

이 후 우리는 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의 Service container

경로 :

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

기본 나뭇 가지 템플릿 :

#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