Ricerca…


Lavora con API RESTFul

REpresentational State Transfer (REST) ​​è uno stile architettonico utilizzato per lo sviluppo web, introdotto e definito nel 2000 da Roy Fielding.

Guardalo su wiki: wiki REST

Si basa su protocollo HTTP ( HTTP su Wiki ), richieste HTTP (GET, POST, PATCH, DELETE ...) / codici di risposte (404, 400, 200, 201, 500 ...) e struttura dei corpi.

Questo è un ottimo modo per esporre i tuoi dati su un altro sistema su Internet.

Immagina di voler creare una API RESTFul per gestire StackOverFlower (utente) sul tuo database locale.

Facciamo l'esempio!

Framework di Symfony 2.8

  1. Server web :

Devi installare e configurare un server web sul tuo computer locale, vedi Wamp o Lamp o Mamp : devi avere una versione recente di PHP ( !!! Requisiti di symfony !!! )

  1. Php cli e Compositore:

Devi configurare PHP cli (variando sul nostro sistema), digita questo "PHP cli [OS-NAME] how-to" nel nostro amico Google! Devi installare compositore, vedi Installazione di Composer

  1. Symfony:

Devi installare Symfony 2.8 (con il compositore, è il modo migliore), aprire un terminale (o cmd su Windows) e andare al percorso del tuo server web.

Symfony 2 funziona con uno dei migliori tipi di struttura: Bundles. Tutti sono pacchetti su Symfony! Possiamo testarlo sopra.

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

Vai alla struttura ad albero e vedi: Symfony 2.8 è installato nella directory "example".

  1. FOSRest (per FriendsOfSymfony) sul pacchetto JMSSerializer:

Devi installare questi due pacchetti:

JMSSerializer ( Installa ):

composer require jms/serializer-bundle "~0.13"

FosRestBundle ( Installa ):

composer require friendsofsymfony/rest-bundle

Non dimenticare di attivarli in AppKernel.php!

  1. Configurazione di base:

Crea il tuo pacchetto "Esempio" e crea il database.

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

Vai in fondo al file di configurazione dell'applicazione Symfony 2.8 e incollalo:

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

Crea la tua directory doctrine ("esempio / src / ExampleBundle / Entity") e il file di risorse ("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

Genera schema entità e aggiornamento:

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

Crea un controller predefinito:

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

Crea la tua vista di Twig predefinita:

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

Hai appena creato la tua prima API RESTFul!

Puoi testarlo su: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflower/new/test .

Come puoi vedere nel databse, è stato creato un nuovo utente con il nome "test".

È possibile ottenere l'elenco di stackover su: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflowers

Hai un esempio completo sul mio account github di questo esempio: esempio di Git Hub , nel ramo "master" questo esempio, e sul "real-routes" branche un esempio con URL più appropriato (come POST e DELETE).

Ci vediamo più tardi per un esempio con SOAP!

I migliori saluti,

Mathieu

Lavora con l'API SOAP

SOAP (Simple Access Object Protocol) è basato su XML, come XML-RPC, è l'antenato , con file chiamato WSDL , che descrive il metodo da esporre.

Questo protocollo è spesso basato su SOAP-Enveloppe , un SOAP-Body e in alternativa SOAP-Header , i dati sono racchiusi in una struttura e interpretati allo stesso modo da diverse lingue.

Descrizione di un messaggio di sapone

Per maggiori informazioni, vedi: SOAP su wiki

Come descritto sopra, il più importante per descrivere il tuo servizio web è il file WSDL , vedi: spiegazione WSDL su wiki

La base del lavoro sarà definire ciò che è esposto sulla tua API SOAP, la tua classe e il tuo processo di business sarà gestito automaticamente dalla classe PHP SOAPServer di base. Hai ancora bisogno del codice!

Vediamo come viene costruito il file:

  1. Servizio: imposta l'URI dell'API e ciò che verrà associato.
  2. Binding: definisce le operazioni associate al servizio
  3. Operazioni: alcuni metodi che si desidera esporre al Web
  4. PortTypes: definisce query e risposte
  5. Richieste e risposte: cosa ti aspetti da input e output
  6. Messaggi: quale formato ti aspetti (parametri) su ogni IO, possono essere semplici (stringa, intero, float ...) o tipo complesso (formato strutturato)

Con queste informazioni di base, puoi ottenere tutte le API che desideri.

Immagina di voler creare un'API SOAP per gestire StackOverFlower (utente) sul tuo database locale.

Facciamo l'esempio!

Installa Web server, Php cli, Composer, Symfony 2.8, crea un nuovo Bundle "ExampleBundle" e crea lo schema come descritto sopra.

Prima di iniziare a costruire la nostra logica di business, abbiamo dovuto sapere cosa esporre del nostro controller. Questo lavoro viene eseguito utilizzando WSDL. Questo è un esempio di una buona sintassi di un 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>

Dobbiamo prendere questo nella tua directory web symfony (nella sottodirectory soap e chiamarlo "stackoverflower.wsdl").

Davvero ispirato all'esempio WSDl . È possibile convalidarlo con un validatore WSDl in linea

Dopo questo, possiamo rendere il nostro servizio di base e controller, ispirato da SOAP Symfony 2.8 Doc .

Servizio, gestito da 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";
  }
}

Configura questo servizio:

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

Come puoi vedere, iniettiamo Doctrine Entity Manger come dipendenza perché dobbiamo usarlo in CRUD StackOverFlower Object.

Controller, che espone l'oggetto servizio:

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

Per ulteriori informazioni sui servizi, consultare: Contenitore di servizi su Symfony doc

La strada :

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

Il modello di ramoscello di base:

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

Abbiamo creato la tua prima API SOAP con Symfony 2.8!

Prima di esporlo, dobbiamo testare !!

Nel tuo StackOverFlowerController, aggiungi questo:

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

I percorsi:

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 }

Puoi digitare questo nel tuo browser:

  1. getList
  2. nuovo
  3. modificare
  4. Elimina

Questo è un esempio molto semplice di un'API non sicura con SOAP, posso fare un esempio di un esempio protetto dietro un'autenticazione della chiave API in seguito.

Che tutti ...

Mathieu



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow