Поиск…


Работа с API RESTFul

REpresentational State Transfer (REST) ​​- это архитектурный стиль, используемый для веб-разработки, введенный и определенный в 2000 году Роем Филдингом.

См. Его на wiki: REST wiki

Он основан на HTTP-протоколе ( HTTP на Wiki ), HTTP-запросах (GET, POST, PATCH, DELETE ...) / кодах ответов (404, 400, 200, 201, 500 ...) и структуре тел.

Это отличный способ разоблачить ваши данные в другой системе в Интернете.

Представьте, что вы хотите сделать RESTFul api для управления вашим StackOverFlower (User) в вашей локальной базе данных.

Давайте сделаем пример!

Концепция Symfony 2.8

  1. Веб сервер :

Вы должны установить и настроить веб-сервер на своей локальной машине, см. Wamp или Lamp или Mamp : у вас должна быть последняя версия PHP ( !!! Требования Symfony !!! )

  1. Php cli и композитор:

Вы должны настроить PHP cli (в зависимости от нашей системы), введите это «PHP-cli [OS-NAME] how-to» в нашего друга Google! Вы должны установить композитор, см. « Установка композитора»

  1. Symfony:

Вы должны установить Symfony 2.8 (с композитором, это лучший способ), открыть терминал (или cmd на окнах) и перейти на ваш веб-сервер.

Symfony 2 работает с одним из лучших типов структуры: Связки. Все - Связки на Symfony! Мы можем проверить это выше.

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

Перейдите к древовидной структуре и увидите: Symfony 2.8 установлен в каталоге «example».

  1. FOSRest (для FriendsOfSymfony) на JMSSerializer Bundle:

Вы должны установить эти два пакета:

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».

Вы можете получить список stackoverflower на: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflowers

У вас есть полный пример в моей учетной записи github этого примера: пример Git Hub , в ветке «master» в этом примере, а в ветке «real-routes» - пример с более подходящим URL (например, POST и DELETE).

Увидимся позже с примером SOAP!

С уважением,

Матье

Работа с SOAP API

SOAP (Протокол объектов простого доступа) основан на XML, например XML-RPC, является предком с файлом WSDL , описывающим метод, который должен быть показан.

Этот протокол часто основан на SOAP-Enveloppe , SOAP-Body и, альтернативно, SOAP-заголовке , данные окутываются в структуру и интерпретируются как один и тот же путь из разных языков.

Описание сообщения Soap

Для получения дополнительной информации см .: SOAP on wiki

Как описано выше, наиболее важным для описания вашего веб-сервиса является файл WSDL , см. Объяснение WSDL в wiki

Основная часть работы будет заключаться в том, чтобы определить, что отображается в вашем SOAP API, ваш класс и ваш бизнес-процесс будут автоматически обрабатываться базовым классом PHP SOAPServer . Вам все еще нужен код!

Посмотрим, как будет построен файл:

  1. Сервис. Установите URI API и то, что будет связано.
  2. Переплет: он определяет операции, связанные с сервисом
  3. Операции: некоторые методы, которые вы хотите открыть в Интернете
  4. PortTypes: определение запросов и ответов
  5. Запросы и ответы: что вы ожидаете ввода и вывода
  6. Сообщения: какой formt вы ожидаете (параметры) для каждого ввода-вывода, они могут быть простыми (string, integer, float ...) или сложным типом (структурированный формат)

С помощью этой базовой информации вы можете достичь всего необходимого API.

Представьте, что вы хотите сделать SOAP api для управления вашим StackOverFlower (Пользователь) в вашей локальной базе данных.

Давайте сделаем пример!

Установите веб-сервер, Php cli, Composer, Symfony 2.8, создайте новый Bundle «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

После этого мы можем сделать наш основной сервис и контроллер, вдохновленные 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]

Как вы можете видеть, мы вставляем Entity Manger в качестве зависимости, потому что мы должны использовать это для объекта CRUD StackOverFlower.

Контроллер, который выставляет объект службы:

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

Мы создали ваш первый SOAP API с Symfony 2.8!

Прежде чем вы откроете его, мы должны проверить!

В вашем 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. удалять

Это очень простой пример не защищенного API с SOAP, и я могу сделать пример защищенного примера после аутентификации ключа api позже.

Что все люди ...

Матье



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow