10 Stimmen

Zend Framework - Wie erstellt man eine API, die sowohl von außen als auch intern zugänglich ist?

Ich möchte eine Website erstellen und zu einem späteren Zeitpunkt eine mobile Anwendung entwickeln.

Ich möchte in der Lage sein, sowohl der Website als auch der App dieselbe Datenebene (d. h. eine Auflistung von Büchern) zur Verfügung zu stellen. Ich würde dafür gerne eine API verwenden, habe aber Schwierigkeiten, Beispiele oder gute Artikel im Internet zu finden.

Ich nehme an, meine Frage ist, wenn ich einen JSON-Endpunkt erstellen würde, auf den eine mobile Anwendung über HTTP zugreifen kann (z. B. http://www.mysite.com/api/v1.0/json ) Wie kann ich auf die gleiche Funktionalität intern von meiner Zend-Anwendung aus zugreifen?

(natürlich möchte ich die Schritte für die Datenbankinteraktion "Modell" nicht duplizieren)

4voto

Stephen Fuhry Punkte 11790

Da Zend nicht wirklich RESTful ist, ist JSON-Rpc leider die beste Lösung.

Sie können es in einem Controller zu tun, oder Sie können nur eine ajax.php zusätzlich zu Ihrem index.php zu reduzieren Overhead wie dieser Kerl tat ici

Im Grunde ist alles, was Sie tun müssen, Folgendes:

$server = new Zend_Json_Server();
$server->setClass('My_Class_With_Public_Methods');
// I've found that a lot of clients only support 2.0
$server->getRequest()->setVersion("2.0");
if ('GET' == $_SERVER['REQUEST_METHOD']) {
    // Indicate the URL endpoint, and the JSON-RPC version used:
    $server->setTarget('/ajax.php')
           ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);

    // Grab the SMD
    $smd = $server->getServiceMap();

    // Return the SMD to the client
    header('Content-Type: application/json');
    echo $smd;
    return;
}

$server->handle();

dann irgendwo in Ihrem Layout:

$server = new Zend_Json_Server();
$server->setClass('My_Class_With_Public_Methods');
$smd = $server->getServiceMap();
?>
<script>
$(document).ready(function() {
    rpc = jQuery.Zend.jsonrpc({
        url : <?=json_encode($this->baseUrl('/ajax'))?>
        , smd : <?=$smd?>
        , async : true
    });
});
</script>

Um ein Beispiel zu geben, hier ist diese Klasse:

class My_Class_With_Public_Methods {
    /**
      * Be sure to properly phpdoc your methods,
      * the rpc clients like it when you do
      * 
      * @param float $param1
      * @param float $param2
      * @return float
      */
    public function someMethodInThatClass ($param1, $param2) {
        return $param1 + $param2;
    }
}

dann können Sie einfach Methoden wie so in Javascript aufrufen:

rpc.someMethodInThatClass(first_param, second_param, {
    // if async = true when you setup rpc,
    // then the last param is an object w/ callbacks
    'success' : function(data) {

    }
    'error' : function(data) {

    }
});

Es gibt nicht viele bekannte JSON-rpc Bibliotheken für Android / iPhone - aber ich habe festgestellt, dass dies mit Zend_Json_Server für Android funktioniert:

http://software.dzhuvinov.com/json-rpc-2.0-base.html

und das funktioniert für das iPhone:

http://www.dizzey.com/development/ios/calling-json-rpc-webservice-in-ios/

Von hier aus können Sie natürlich My_Class_With_Public_Methods auf die gleiche Weise verwenden, wie es Javascript / Ihre mobile App tut.

1voto

netcoder Punkte 64375

Aus meiner Sicht ist dies eher eine Frage der Architektur als eine Frage des Zend Frameworks.

Was Sie suchen, ist eine serviceorientierte Architektur (SOA).

Die Prämisse, die hinter SOA steht, ist einfach: Man baut eine einzige API und lässt alles über diese laufen, egal ob intern oder extern. Ein beliebter Befürworter von SOA ist Amazon.

In der Praxis bedeutet dies, dass Sie Ihre API genau so offenlegen, wie Sie sie intern verwenden würden. In der OOP bedeutet dies, dass Sie bei jedem Aufruf Ihrer API von einer externen Quelle (z. B. einer REST-API) einen Klassennamen, einen Methodennamen und eine Liste von Argumenten angeben und ein Objekt zurückerhalten, genauso wie Sie es intern aufrufen würden.

Zum Beispiel haben Sie diese:

class HelloInstance {
    public $hello;
    public function __construct($hello) { $this->hello = $hello; }
}

class Hello {
    public function getHello() { return new HelloInstance('world'); }
}

class FooInstance {
    public $foo;
    public function __construct($foo) { $this->foo = $foo; }
}

class Foo {
    public function getFoo($value) { return new FooInstance($value); }
}

Wenn Sie sie intern verwenden wollen, können Sie das tun:

$hello = new Hello;
$helloInst = $hello->getHello();

$foo = new Foo;
$fooInst = $foo->getFoo('bar');

Jetzt brauchen Sie nur noch ein Gateway, um diese API nach außen zu tragen. Hier ist ein sehr einfaches Beispiel:

include_once 'my_classes.php';

$class = $_GET['class'];
$method = $_GET['method'];

$obj = new $class;
$return = $obj->$method(isset($_GET['value']) ? $_GET['value'] : null);

header('Content-Type: application/json');
echo json_encode($return);

Mit einem REST-Aufruf können Sie dieselben beiden Aufrufe durchführen, die ich zuvor gezeigt habe, und erhalten dieselben Ergebnisse:

http://my_server/my_gateway.php?class=Hello&method=getHello
http://my_server/my_gateway.php?class=Foo&method=getFoo&value=bar

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X