I'm looking to create a web site and will be creating a mobile app at a later date.
I want to be able to offer the same level of data (i.e. a listing of books) to both the web site and the app. I'd like to use an API for this but am struggling to find any examples or decent articles online.
So I suppose my question is, if I were to create a JSON 'endpoint' accessible by a mobile app over HTTP (e.g. http://www.mysite.com/api/v1.0/json) how do access the same functionality internally from my Zend Application?
(obviously I don't want to duplicate the database interaction 'model' steps)
Since Zend is really not RESTful, unfortunately, your best bet is JSON-Rpc.
You can do it in a controller, or you can just make an ajax.php in addition to your index.php to reduce overhead like this guy did here
Basically, all you need to do is this:
$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();
then somewhere in your 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>
for the sake of example, here's that class:
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;
}
}
then you can simply call methods like so in javascript:
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) {
}
});
There aren't a lot of well known JSON-rpc libraries for Android / iPhone - but I have found that this works with Zend_Json_Server for Android:
http://software.dzhuvinov.com/json-rpc-2.0-base.html
and this works for iPhone:
http://www.dizzey.com/development/ios/calling-json-rpc-webservice-in-ios/
From here, obviously, you can use My_Class_With_Public_Methods in the same way that javascript / your mobile app does.
From my point of view, this is more an architecture-related question than a Zend Framework question.
What you are looking for is Service-Oriented Architecture (SOA).
The premise behind SOA is simple, build a single API, and have everything go through it, whether it is internally, or externally. A popular proponent of SOA is Amazon.
In practice, it means that you expose your API exactly as you would use it internally. In OOP, this means that whenever you call your API from an external source (e.g.: a REST API), you'll specify a class name, a method name and a list of arguments, and you'll receive a object in return, just as you would if you'd call it internally.
Per example, you have these:
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); }
}
If you want to use them internally, you'd do:
$hello = new Hello;
$helloInst = $hello->getHello();
$foo = new Foo;
$fooInst = $foo->getFoo('bar');
Now you just need a gateway to expose this API externally. Here's a very basic example:
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);
You can do the same two calls I demonstrated before, and get the same results, using a REST call:
http://my_server/my_gateway.php?class=Hello&method=getHello
http://my_server/my_gateway.php?class=Foo&method=getFoo&value=bar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With