Поиск…
Работа с 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
- Веб сервер :
Вы должны установить и настроить веб-сервер на своей локальной машине, см. Wamp или Lamp или Mamp : у вас должна быть последняя версия PHP ( !!! Требования Symfony !!! )
- Php cli и композитор:
Вы должны настроить PHP cli (в зависимости от нашей системы), введите это «PHP-cli [OS-NAME] how-to» в нашего друга Google! Вы должны установить композитор, см. « Установка композитора»
- 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».
- FOSRest (для FriendsOfSymfony) на JMSSerializer Bundle:
Вы должны установить эти два пакета:
JMSSerializer ( установить ):
composer require jms/serializer-bundle "~0.13"
FosRestBundle ( установить ):
composer require friendsofsymfony/rest-bundle
Не забудьте активировать их в AppKernel.php!
- Основная конфигурация:
Создайте свой собственный «пример» и создайте базу данных.
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 on wiki
Как описано выше, наиболее важным для описания вашего веб-сервиса является файл WSDL , см. Объяснение WSDL в wiki
Основная часть работы будет заключаться в том, чтобы определить, что отображается в вашем SOAP API, ваш класс и ваш бизнес-процесс будут автоматически обрабатываться базовым классом PHP SOAPServer . Вам все еще нужен код!
Посмотрим, как будет построен файл:
- Сервис. Установите URI API и то, что будет связано.
- Переплет: он определяет операции, связанные с сервисом
- Операции: некоторые методы, которые вы хотите открыть в Интернете
- PortTypes: определение запросов и ответов
- Запросы и ответы: что вы ожидаете ввода и вывода
- Сообщения: какой 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 }
Вы можете ввести его в своем браузере:
Это очень простой пример не защищенного API с SOAP, и я могу сделать пример защищенного примера после аутентификации ключа api позже.
Что все люди ...
Матье