Suche…
Arbeiten Sie mit der RESTFul-API
REpresentational State Transfer (REST) ist ein Architekturstil für die Webentwicklung, der im Jahr 2000 von Roy Fielding eingeführt und definiert wurde.
Siehe im Wiki: REST Wiki
Es basiert auf dem HTTP-Protokoll ( HTTP auf Wiki ), HTTP-Anforderungen (GET, POST, PATCH, DELETE ...) / Antwortcodes (404, 400, 200, 201, 500 ...) und Körperstruktur.
Auf diese Weise können Sie Ihre Daten einem anderen System im Internet zugänglich machen.
Stellen Sie sich vor, Sie möchten eine RESTFul-API erstellen, um Ihren StackOverFlower (Benutzer) in Ihrer lokalen Datenbank zu verwalten.
Lass uns das Beispiel machen!
Symfony 2.8-Framework
- Webserver:
Sie müssen einen Webserver auf Ihrem lokalen Computer installieren und konfigurieren, siehe Wamp oder Lamp oder Mamp : Sie benötigen eine aktuelle Version von PHP ( !!! Symfony-Anforderungen !!! ).
- PHP cli und Komponist:
Sie müssen PHP cli konfigurieren (abhängig von unserem System) und geben Sie dieses "PHP cli [OS-NAME] -Hinweise" in unserem Freund Google ein! Sie müssen Composer installieren , siehe Composer-Installation
- Symfony:
Sie müssen Symfony 2.8 installieren (mit Composer ist dies der bessere Weg), ein Terminal (oder cmd unter Windows) öffnen und zu Ihrem Webserverpfad wechseln.
Symfony 2 arbeitet mit einem der besseren Strukturtypen: Bundles. Alle sind Bundles bei Symfony! Wir können es oben testen.
cd /your-web-server-path/
composer create-project symfony/framework-standard-edition example "2.8.*"
Gehen Sie zur Baumstruktur und sehen Sie: Symfony 2.8 wird im Verzeichnis "example" installiert.
- FOSRest (für FriendsOfSymfony) auf JMSSerializer Bundle:
Sie müssen diese beiden Bundles installieren:
JMSSerializer ( Installieren ):
composer require jms/serializer-bundle "~0.13"
FosRestBundle ( Installieren ):
composer require friendsofsymfony/rest-bundle
Vergiss nicht, sie in AppKernel.php zu aktivieren!
- Grundlegende Einstellung :
Stellen Sie Ihr eigenes "Beispiel" -Paket zusammen und erstellen Sie die Datenbank.
cd /path/to/your/symfony/
php app/console generate:bundle
php app/console doctrine:generate:database
Gehen Sie zum Ende Ihrer Symfony 2.8-Anwendungskonfigurationsdatei und fügen Sie sie ein:
#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 }
Erstellen Sie Ihr Doctrine-Verzeichnis ("example / src / ExampleBundle / Entity") und die Ressourcendatei ("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
Entity generieren und Schema aktualisieren:
php app/console doctrine:generate:entity StackOverFlower
php app/console doctrine:schema:update --force
Erstellen Sie einen Standardcontroller:
#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);
}
}
Erstellen Sie Ihre standardmäßige Zweigansicht:
#src/ExampleBundle/Resources/views/StackOverFlower.html.twig
{% if errors is defined %}
{{ errors }}
{% else %}
{% if users is defined %}
{{ users | serialize }}
{% else %}
{{ user | serialize }}
{% endif %}
{% endif %}
Sie haben gerade Ihre erste RESTFul-API erstellt!
Sie können es unter folgender Adresse testen: http: //Ihr-Servername/Ihr-Symfony-Pfad/app_dev.php/stackoverflower/new/test .
Wie Sie in der Datenbank sehen können, wurde ein neuer Benutzer mit dem Namen "test" erstellt.
Sie finden die Liste der stackoverflower unter: http: //Ihr-Servername/Ihr-symfony-Pfad/app_dev.php/stackoverflowers
Auf meinem Github-Konto haben Sie ein vollständiges Beispiel für dieses Beispiel: Git Hub-Beispiel , im Zweig "master" dieses Beispiel und in der Branche "echte Routen" ein Beispiel mit einer geeigneteren URL (wie POST und DELETE).
Wir sehen uns später für ein Beispiel mit SOAP!
Freundliche Grüße,
Mathieu
Arbeiten Sie mit der SOAP-API
SOAP (Simple Access Object Protocol) ist XML-basiert, wie XML-RPC, ein Vorfahr mit der Datei WSDL , die die offengelegte Methode beschreibt.
Dieses Protokoll basiert oft auf SOAP-Enveloppe , einem SOAP-Body und alternativ SOAP-Header . Die Daten werden in eine Struktur eingeschlossen und werden auf dieselbe Weise aus verschiedenen Sprachen interpretiert.
Weitere Informationen finden Sie unter SOAP im Wiki
Wie oben beschrieben, ist die WSDL- Datei am wichtigsten, um Ihren Web-Service zu beschreiben. Siehe WSDL-Erläuterung im Wiki
Die Basis der Arbeit besteht darin, zu definieren, was auf Ihrer SOAP-API verfügbar ist . Ihre Klasse und Ihr Geschäftsprozess werden automatisch von der grundlegenden PHP-Klasse SOAPServer verarbeitet . Du brauchst noch den Code!
Mal sehen, wie die Datei aufgebaut ist:
- Service: Legen Sie den API-URI und die zuzuordnende Komponente fest.
- Bindung: Definiert die Vorgänge, die dem Dienst zugeordnet sind
- Vorgänge: Einige Methoden, die Sie für das Web verfügbar machen möchten
- PortTypes: Definieren Sie Abfragen und Antworten
- Anfragen und Antworten: was Sie von Input und Output erwarten
- Meldungen: Welche Form (Parameter) erwarten Sie für jede E / A? Sie können einfache (String, Integer, Float ...) oder komplexe Typen (strukturiertes Format) sein.
Mit diesen grundlegenden Informationen können Sie alle gewünschten APIs erreichen.
Stellen Sie sich vor, Sie möchten eine SOAP-API erstellen, um Ihren StackOverFlower (Benutzer) in Ihrer lokalen Datenbank zu verwalten.
Lass uns das Beispiel machen!
Installieren Sie den Webserver, PHP, Composer, Symfony 2.8, erstellen Sie ein neues Bundle "ExampleBundle" und erstellen Sie das Schema wie oben beschrieben.
Bevor wir mit dem Aufbau unserer Geschäftslogik beginnen, mussten wir wissen, was mit unserem Controller zu tun ist. Diese Aufgabe wird mithilfe der WSDL ausgeführt. Dies ist ein Beispiel für eine gute Syntax einer 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>
Wir müssen dies in Ihrem Web-Symfony-Verzeichnis (im soap-Unterverzeichnis und "stackoverflower.wsdl") nennen.
Wirklich inspiriert vom WSDl-Beispiel . Sie können dies mit einem Online-WSDl-Validator überprüfen
Danach können wir unseren grundlegenden Service und Controller aus SOAP Symfony 2.8 Doc .
Dienst, der von PHP SOAPServer abgewickelt wird:
#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";
}
}
Konfigurieren Sie diesen Dienst:
#src\ExampleBundle\Resources\config\services.yml
services:
stackoverflower_service:
class: ExampleBundle\Services\StackOverFlowerService
arguments: [@doctrine.orm.entity_manager]
Wie Sie sehen, injizieren wir den Doctrine Entity Manager als Abhängigkeit, da wir dies für das CRUD StackOverFlower-Objekt verwenden müssen.
Controller, der das Serviceobjekt verfügbar macht:
#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;
}
}
Weitere Informationen zu Diensten finden Sie unter Dienstcontainer in Symfony doc
Die Route:
example_soap:
path: /soap
defaults: { _controller: ExampleBundle:StackOverFlower:index }
Die grundlegende Twig-Vorlage:
#src\ExampleBundle\Resources\views\Soap\default.html.twig
{% if status is defined %}
{{ status }}
{% else %}
{{ list }}
{% endif %}
Wir haben Ihre erste SOAP-API mit Symfony 2.8 erstellt!
Bevor Sie es entlarven, müssen wir testen !!
Fügen Sie in Ihrem StackOverFlowerController Folgendes hinzu:
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);
Die Routen:
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 }
Sie können dies in Ihrem Browser eingeben:
Dies ist ein sehr einfaches Beispiel für eine nicht gesicherte API mit SOAP. Ich kann später ein Beispiel für ein gesichertes Beispiel hinter einer API-Schlüsselauthentifizierung ausführen.
Dass alle Leute...
Mathieu