Szukaj…


Pracuj z RESTFul API

REpresentational State Transfer (REST) to styl architektoniczny używany do tworzenia stron internetowych, wprowadzony i zdefiniowany w 2000 roku przez Roy Fieldinga.

Zobacz na wiki: REST wiki

Opiera się na protokole HTTP ( HTTP na Wiki ), żądaniach HTTP (GET, POST, PATCH, DELETE ...) / kodach odpowiedzi (404, 400, 200, 201, 500 ...) i strukturze treści.

To świetny sposób na udostępnienie danych innym systemowi w Internecie.

Wyobraź sobie, że chcesz utworzyć interfejs API RESTFul do zarządzania StackOverFlower (użytkownik) w lokalnej bazie danych.

Zróbmy przykład!

Framework Symfony 2.8

  1. Serwer internetowy :

Musisz zainstalować i skonfigurować serwer WWW na swoim komputerze lokalnym, zobacz Wamp lub Lamp lub Mamp : Musisz mieć najnowszą wersję PHP ( !!! Wymagania Symfony !!! )

  1. Php cli i kompozytor:

Musisz skonfigurować PHP cli (w zależności od naszego systemu), wpisać „PHP cli [NAZWA OS-a] w naszym przyjacielu Google! Musisz zainstalować kompozytora, patrz Instalacja kompozytora

  1. Symfony:

Musisz zainstalować Symfony 2.8 (z kompozytorem, to lepszy sposób), otworzyć terminal (lub cmd w systemie Windows) i przejść do ścieżki serwera WWW.

Symfony 2 działa z jednym z lepszych typów struktur: pakietami. Wszystkie są pakietami w Symfony! Możemy to przetestować powyżej.

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

Przejdź do struktury drzewa i zobacz: Symfony 2.8 jest zainstalowany w katalogu „example”.

  1. FOSRest (dla FriendsOfSymfony) w pakiecie JMSSerializer:

Musisz zainstalować te dwa pakiety:

JMSSerializer ( instalacja ):

composer require jms/serializer-bundle "~0.13"

FosRestBundle ( instalacja ):

composer require friendsofsymfony/rest-bundle

Nie zapomnij aktywować ich w AppKernel.php!

  1. Podstawowa konfiguracja:

Stwórz własny pakiet „Przykład” i utwórz bazę danych.

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

Przejdź do dolnej części pliku konfiguracyjnego aplikacji Symfony 2.8 i wklej go:

#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 }

Utwórz katalog doctrine („example / src / ExampleBundle / Entity”) i plik zasobów („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

Generuj encję i aktualizuj schemat:

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

Stwórz domyślny kontroler:

#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);
    }
}

Ustaw domyślny widok gałązki:

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

Właśnie utworzyłeś swój pierwszy interfejs API RESTFul!

Możesz to przetestować na: http: // twoja-nazwa-serwera/twoja-symfony-path/app_dev.php/stackoverflower/new/test .

Jak widać w bazie danych, utworzono nowego użytkownika o nazwie „test”.

Możesz uzyskać listę stackoverflower na stronie: http: //nazwa-serwera-serwis/twoja-symfony-path/app_dev.php/stackoverflowers

Masz pełny przykład na moim koncie github tego przykładu: przykład Git Hub , w gałęzi „master” ten przykład, a na „real-trasy” rozgałęzia się przykład z bardziej odpowiednim adresem URL (takim jak POST i DELETE).

Do zobaczenia później z przykładem SOAP!

Z poważaniem,

Mathieu

Pracuj z SOAP API

SOAP (Simple Access Object Protocol) jest oparty na XML, podobnie jak XML-RPC, jest przodkiem , z plikiem o nazwie WSDL , który opisuje metodę, która ma być ujawniona.

Protokół ten często opiera się na SOAP-Enveloppe , SOAP-Body i alternatywnie SOAP-Header , dane są otoczone strukturą i interpretowane w ten sam sposób z różnych języków.

Opis komunikatu o mydle

Aby uzyskać więcej informacji, zobacz: SOAP na wiki

Jak opisano powyżej, najważniejsze do opisania twojej usługi internetowej jest plik WSDL , patrz: Objaśnienie WSDL na wiki

Podstawowym zadaniem będzie zdefiniowanie tego, co jest widoczne w interfejsie API SOAP, twoja klasa i proces biznesowy będą automatycznie obsługiwane przez podstawową klasę PHP SOAPServer . Nadal potrzebujesz kodu!

Zobaczmy, jak skonstruowany jest plik:

  1. Usługa: ustaw identyfikator URI interfejsu API i elementy, które zostaną powiązane.
  2. Wiązanie: określa operacje związane z usługą
  3. Operacje: niektóre metody, które chcesz udostępnić w Internecie
  4. PortTypes: definiuj zapytania i odpowiedzi
  5. Żądania i odpowiedzi: czego oczekujesz od danych wejściowych i wyjściowych
  6. Komunikaty: jakiego formatu oczekujesz (parametry) na każdym We / Wy, mogą być proste (łańcuch, liczba całkowita, liczba zmiennoprzecinkowa ...) lub typ złożony (format strukturalny)

Dzięki tym podstawowym informacjom możesz uzyskać wszystkie interfejsy API, jakie chcesz.

Wyobraź sobie, że chcesz utworzyć interfejs SOAP do zarządzania StackOverFlower (użytkownik) w lokalnej bazie danych.

Zróbmy przykład!

Zainstaluj serwer WWW, Php cli, Composer, Symfony 2.8, utwórz nowy pakiet „ExampleBundle” i zbuduj schemat jak opisano powyżej.

Zanim zaczęliśmy budować naszą logikę biznesową, musieliśmy wiedzieć, co ujawnić naszemu kontrolerowi. To zadanie jest wykonywane przy użyciu WSDL. To jest przykład dobrej składni 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>

Musimy wziąć to do twojego internetowego katalogu symfony (w podkatalogu mydło i nazwać to „stackoverflower.wsdl”).

Naprawdę zainspirowany przykładem WSDl . Możesz to sprawdzić za pomocą walidatora WSDl Online

Następnie możemy uczynić naszą podstawową usługę i kontroler inspirowanymi SOAP Symfony 2.8 Doc .

Usługa obsługiwana przez 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";
  }
}

Skonfiguruj tę usługę:

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

Jak widać, wstrzykujemy Doctrine Entity Manger jako zależność, ponieważ musimy go użyć do CRUD StackOverFlower Object.

Kontroler, który udostępnia obiekt usługi:

#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;
  }
}

Aby dowiedzieć się więcej o usługach, zobacz: Kontener usług w dokumencie Symfony

Trasa :

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

Podstawowy szablon gałązki:

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

Zrobiliśmy twój pierwszy SOAP API z Symfony 2.8!

Zanim go ujawnisz, musimy przetestować !!

W swoim StackOverFlowerController dodaj to:

  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); 

Trasy:

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 }

Możesz wpisać to w swojej przeglądarce:

  1. getList
  2. Nowy
  3. edytować
  4. usunąć

Jest to bardzo podstawowy przykład niezabezpieczonego interfejsu API z SOAP, później mogę zrobić przykład zabezpieczonego przykładu uwierzytelnienia za pomocą klucza API.

Że wszyscy ludzie ...

Mathieu



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow