Zoeken…


Werk met RESTFul API

REPResentational State Transfer (REST) is een architecturale stijl die wordt gebruikt voor webontwikkeling, geïntroduceerd en gedefinieerd in 2000 door Roy Fielding.

Bekijk het op wiki: REST wiki

Het is gebaseerd op HTTP-protocol ( HTTP op Wiki ), HTTP-aanvragen (GET, POST, PATCH, DELETE ...) / responscodes (404, 400, 200, 201, 500 ...) en structuur van het lichaam.

Dit is een geweldige manier om uw gegevens aan een ander systeem op internet bloot te stellen.

Stel je voor dat je een RESTFul-api wilt maken om je StackOverFlower (gebruiker) in je lokale database te beheren.

Laten we het voorbeeld maken!

Symfony 2.8 framework

  1. Web Server :

U moet een webserver op uw lokale computer installeren en configureren, zie Wamp of Lamp of Mamp : U moet een recente versie van PHP hebben ( !!! Symfony-vereisten !!! )

  1. Php cli en componist:

U moet PHP cli configureren (afhankelijk van ons systeem), typ deze "PHP cli [OS-NAME] how-to" in onze vriend Google! U moet componist installeren, zie Composer installeren

  1. Symfony:

U moet Symfony 2.8 installeren (met componist, het is de betere manier), een terminal openen (of cmd op Windows) en naar uw webserverpad gaan.

Symfony 2 werkt met een van de betere structuurtypen: bundels. Het zijn allemaal bundels op Symfony! We kunnen het hierboven testen.

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

Ga naar de boomstructuur en zie: Symfony 2.8 is geïnstalleerd in de map "voorbeeld".

  1. FOSRest (voor FriendsOfSymfony) op JMSSerializer-bundel:

U moet deze twee bundels installeren:

JMSSerializer ( installeren ):

composer require jms/serializer-bundle "~0.13"

FosRestBundle ( installeren ):

composer require friendsofsymfony/rest-bundle

Vergeet ze niet te activeren in AppKernel.php!

  1. Basis configuratie:

Maak uw eigen "Voorbeeld" -bundel en maak de database.

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

Ga onderaan in het configuratiebestand van uw Symfony 2.8-toepassing en plak het:

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

Maak uw doctrine-map ("example / src / ExampleBundle / Entity") en resourcebestand ("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

Entiteit genereren en schema bijwerken:

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

Maak een standaardcontroller:

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

Maak uw standaard Twig-weergave:

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

U hebt zojuist uw eerste RESTFul API gemaakt!

Je kunt het testen op: http: //uw-servernaam/uw-symfony-path/app_dev.php/stackoverflower/new/test .

Zoals u in de database kunt zien, is een nieuwe gebruiker gemaakt met de naam "test".

U kunt de lijst met stackoverflower krijgen op: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflowers

Je hebt een volledig voorbeeld op mijn github-account van dit voorbeeld: Git Hub-voorbeeld , bij de "master" vertakking van dit voorbeeld, en in de "real-routes" -branche een voorbeeld met meer geschikte URL (zoals POST en DELETE).

Tot later voor een voorbeeld met SOAP!

Beste wensen,

Mathieu

Werk met SOAP API

SOAP (Simple Access Object Protocol) is op XML gebaseerd, net als XML-RPC, is een voorouder , met het bestand WSDL , wat de bloot te leggen methode beschrijft.

Dit protocol is vaak gebaseerd op SOAP-Enveloppe , een SOAP-body en als alternatief SOAP-header , de gegevens zijn in een structuur gehuld en kunnen op dezelfde manier worden geïnterpreteerd vanuit verschillende talen.

Beschrijving van een zeepbericht

Zie voor meer informatie: SOAP op wiki

Zoals hierboven beschreven, is het belangrijkste om uw webservice te beschrijven het WSDL- bestand, zie: WSDL-uitleg op wiki

De basis van het werk zal zijn om te definiëren wat zichtbaar is op uw SOAP API, uw klasse en uw bedrijfsproces worden automatisch afgehandeld door de basis PHP SOAPServer- klasse. Je hebt nog steeds de code nodig!

Laten we eens kijken hoe het bestand is opgebouwd:

  1. Service: stel de API URI in en wat hieraan wordt gekoppeld.
  2. Binding: definieert de bewerkingen die aan de service zijn gekoppeld
  3. Bewerkingen: sommige methoden die u op internet wilt blootleggen
  4. PortTypes: definieer vragen en antwoorden
  5. Verzoeken en antwoorden: wat u input en output verwacht
  6. Berichten: welke indeling u verwacht (parameters) op elke IO, ze kunnen eenvoudig zijn (tekenreeks, geheel getal, zwevend ...) of complex type (gestructureerd formaat)

Met deze basisinformatie kunt u alle API's bereiken die u wilt.

Stel je voor dat je een SOAP-API wilt maken om je StackOverFlower (gebruiker) in je lokale database te beheren.

Laten we het voorbeeld maken!

Installeer de webserver, Php cli, Composer, Symfony 2.8, maak een nieuwe bundel "ExampleBundle" en bouw het schema zoals hierboven beschreven.

Voordat we onze bedrijfslogica gingen bouwen, moesten we weten wat we van onze controller moesten vrijgeven. Deze taak wordt uitgevoerd met behulp van de WSDL. Dit is een voorbeeld van een goede syntaxis van een 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>

We moeten dit meenemen naar uw web symfony-directory (in soap-submap en deze "stackoverflower.wsdl" noemen).

Echt geïnspireerd door WSDl-voorbeeld . U kunt dat valideren met een online WSDl-validator

Hierna kunnen we onze basisservice en controller maken, geïnspireerd door SOAP Symfony 2.8 Doc .

Service, die wordt afgehandeld door 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";
  }
}

Configureer deze service:

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

Zoals u ziet, injecteren we de Doctrine Entity Manger als een afhankelijkheid omdat we dit moeten gebruiken voor CRUD StackOverFlower Object.

Controller, die het serviceobject blootstelt:

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

Zie voor meer informatie over services: Servicecontainer op Symfony doc

De route :

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

De basistaksjabloon:

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

We hebben uw eerste SOAP-API gemaakt met Symfony 2.8!

Voordat u het blootstelt, moeten we testen !!

Voeg in uw StackOverFlowerController dit toe:

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

De routes:

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 }

U kunt dit in uw browser typen:

  1. GetList
  2. nieuw
  3. Bewerk
  4. verwijderen

Dit is een heel eenvoudig voorbeeld van een niet-beveiligde API met SOAP, ik kan later een voorbeeld van een beveiligd voorbeeld achter een authenticatie van een api-sleutel maken.

Dat alle mensen ...

Mathieu



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow