Mit Apigility kann jeder Entwickler per Administrationsoberfläche einen REST oder RPC Web Service erstellen und betreiben. Apigility unterstützt zahlreiche Features wie HAL-JSON, Fehlerbehandlung, Versionierung, Authentifizierung und Dokumentation. Dies klappt prima für einfach strukturierte APIs. Doch können auch komplexere Strukturen umgesetzt werden oder stößt man hierbei schnell an die Grenzen? Dieser Vortrag zeigt Ihnen, wann Sie selber Hand an den generierten Code anlegen müssen und warum der Einsatz von Apigility auch bei komplexeren Services viel Sinn macht.
8. RReessttffuull WWeebb SSeerrvviicceess
CLIENT
Web Browser
PHP
Javascript
RUBY
PYTHON
REST SERVER
/api/user/123
/api/user
/api/user
/api/user/123
/api/user/123
USER DOMAIN
getUserEntity()
getUserCollection()
addUserEntity()
updateUserEntity()
deleteUserEntity()
GET Request
JSON Response
GET Request
JSON Response
POST Request
JSON Response
PUT Request
JSON Response
DELETE Request
JSON Response
Integer
UserEntity
void
UserCollection
Array
Boolean
Integer, Array
Boolean
Integer
Boolean
8 / 46
9. RRPPCC WWeebb SSeerrvviicceess
Local
CLIENT
javascript
RPC
Client
JSON
Method:getUser
Params:id
USER DOMAIN
getUserEntity()
GET Request
JSON Result
Integer
UserEntity
RPC
Server
/json-rpc.php
Remote Call
JSON Result
javascript
JSON
Method:addUser
Params:name
addUserEntity()
POST Request
JSON Result
Array
Boolean
/json-rpc.php
Remote Call
JSON Result
javascript
XML
Method:getUser
Params:id
getUserEntity()
GET Request
XML Result
Integer
UserEntity
/xml-rpc.php
Remote Call
XML Result
javascript
XML
Method:addUser
Params:name
addUserEntity()
POST Request
XML Result
Array
Boolean
/xml-rpc.php
Remote Call
XML Result
9 / 46
28. UUsseerr TTaabbllee II
// module/User/src/User/V3/Rest/UserProfiles/Table/UserTable.php
namespace UserV3RestUserProfilesTable;
use ZendDbAdapterAdapterInterface;
use ZendDbResultSetResultSetInterface;
use ZendDbTableGatewayTableGateway;
class UserTable extends TableGateway
{
public function __construct(
AdapterInterface $adapter,
ResultSetInterface $resultSetPrototype = null
) {
$table = 'users';
parent::__construct($table, $adapter, null, $resultSetPrototype);
}
public function fetchUserById($id)
{
$select = $this->getSql()->select();
$select->where->equalTo('id', $id);
return $this->selectWith($select)->current();
}
28 / 46
29. UUsseerr TTaabbllee IIII
[...]
public function fetchContactsById($id)
{
$select = $this->getSql()->select();
$select->join('user_contacts', 'user_id_2 = id', array());
$select->where->equalTo('user_id_1', $id);
return $this->selectWith($select)->toArray();
}
public function fetchUsers($params)
{
$select = $this->getSql()->select();
return $this->selectWith($select)->toArray();
}
}
29 / 46
30. UUsseerr TTaabbllee IIIIII
// module/User/src/User/V3/Rest/UserProfiles/Table/UserTableFactory.php
namespace UserV3RestUserProfilesTable;
use ZendDbResultSetResultSet;
use ZendServiceManagerFactoryInterface;
use ZendServiceManagerServiceLocatorInterface;
class UserTableFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$dbAdapter = $serviceLocator->get('MysqlAdapter');
$resultSet = new ResultSet(ResultSet::TYPE_ARRAY);
$table = new UserTable($dbAdapter, $resultSet);
return $table;
}
}
30 / 46
31. UUsseerr PPrrooffiillee eennttiittyy
// module/User/src/User/V3/Rest/UserProfiles/UserProfilesEntity.php
namespace UserV3RestUserProfiles;
class UserProfilesEntity
{
protected $id;
protected $firstname;
protected $lastname;
protected $email;
protected $contacts;
protected $websites;
public function setId($id) {}
public function getId() {}
public function setFirstname($firstname) {}
public function getFirstame() {}
public function setLastname($lastname) {}
public function getLastame() {}
public function setEmail($email) {}
public function getEmail() {}
public function setContacts(array $contacts) {}
public function getContacts() {}
public function setWebsites(array $websites) {}
public function getWebsites() {}
}
31 / 46
32. UUsseerr PPrrooffiillee RReessoouurrccee II
// module/User/src/User/V3/Rest/UserProfiles/UserProfilesResource.php
namespace UserV3RestUserProfiles;
use UserV3RestUserProfileTableUserTable;
use UserV3RestUserProfileTableWebsiteTable;
use ZFApiProblemApiProblem;
use ZFRestAbstractResourceListener;
class UserProfilesResource extends AbstractResourceListener
{
protected $userTable;
protected $websiteTable;
public function setUserTable($userTable) {}
public function getUserTable() {}
public function setWebsiteTable($websiteTable) {}
public function getWebsiteTable() {}
public function create($data)
{
return new ApiProblem(405, 'The POST method has not been defined');
}
public function delete($id) {}
public function deleteList($data) {}
32 / 46
33. UUsseerr PPrrooffiillee RReessoouurrccee IIII
public function fetch($id)
{
$user = $this->getUserTable()->fetchUserById($id);
if (!$user) {
return new ApiProblem(404, 'User profile for id ' . $id . ' not found');
}
return $this->addContactsAndWebsites($user);
}
public function fetchAll($params = array())
{
$users = $this->getUserTable()->fetchUsers($params);
if (!$users) {
return new ApiProblem(404, 'No user profiles found');
}
foreach ($users as $key => $user) {
$users[$key] = $this->addContactsAndWebsites($user);
}
return $users;
}
protected function addContactsAndWebsites(array $user)
{
$user['contacts'] = $this->getUserTable()->fetchContactsById($user['id']);
$user['websites'] = $this->getWebsiteTable()->fetchWebsitesById($user['id']);
return $user;
}
}
33 / 46
34. UUsseerr PPrrooffiillee RReessoouurrccee IIIIII
// module/User/src/User/V3/Rest/UserProfiles/UserProfilesResourceFactory.php
namespace UserV3RestUserProfiles;
class UserProfilesResourceFactory
{
public function __invoke($services)
{
$userTable = $services->get(
'UserV2RestUserProfileTableUserTable'
);
$websiteTable = $services->get(
'UserV2RestUserProfileTableWebsiteTable'
);
$resource = new UserProfilesResource();
$resource->setUserTable($userTable);
$resource->setWebsiteTable($websiteTable);
return $resource;
}
}
34 / 46
46. BBiillddnnaacchhwweeiiss
[B00] Fotos von Ralf Eggert
[B01] Still here https://www.flickr.com/photos/thenovys/3784261365 von Abe Novy - CC-BY https://creativecommons.org/licenses/by/2.0/
[B02] Young student https://www.flickr.com/photos/audiolucistore/14159712431/ von www.audio-luci-store.it - CC-BY https://creativecommons.org/licenses/by/2.0/
[B03] Acorns https://www.flickr.com/photos/dno1967b/5431273344 von Daniel Oines - CC-BY https://creativecommons.org/licenses/by/2.0/
[B04] Fixing the database https://www.flickr.com/photos/dahlstroms/4140461901 von Håkan Dahlström - CC-BY https://creativecommons.org/licenses/by/2.0/
[B05] Monaco 14pt https://www.flickr.com/photos/polarity/3138680190 von Robert Agthe - CC-BY https://creativecommons.org/licenses/by/2.0/
[B06] RSA Securid Token - Credit Card Style https://www.flickr.com/photos/purpleslog/265657780 von Purple Slog - CC-BY https://creativecommons.org/licenses/by/2.0/
[B07] Shelf of Used Books https://www.flickr.com/photos/thedarkthing/5363586197 von William Ross - CC-BY https://creativecommons.org/licenses/by/2.0/
[B08] Ticket validator at Nice train station https://www.flickr.com/photos/traveleden/3797157077 von Simon - CC-BY https://creativecommons.org/licenses/by/2.0/
[B09] Test Lab - Supermicro Storage https://www.flickr.com/photos/jemimus/8533890844 von Robert - CC-BY https://creativecommons.org/licenses/by/2.0/
[B10] Building blocks https://www.flickr.com/photos/zscheyge/49012397 von Holger Zscheyge - CC-BY https://creativecommons.org/licenses/by/2.0/
[B11] Bluetooth adapter https://www.flickr.com/photos/razor512/8201846881 von Razor512 - CC-BY https://creativecommons.org/licenses/by/2.0/
[B12] Busy Postmen https://www.flickr.com/photos/wheatfields/4253690499 von Christian Guthier - CC-BY https://creativecommons.org/licenses/by/2.0/
[B13] Filters for black and white film https://www.flickr.com/photos/aslakr/96723190 von Aslak Raanes - CC-BY https://creativecommons.org/licenses/by/2.0/
[B14] Cable closet https://www.flickr.com/photos/adrian_s/8271860 von Adrian Sampson - CC-BY https://creativecommons.org/licenses/by/2.0/
[B15] Cauliflower https://www.flickr.com/photos/calliope/54833239 von Liz West - CC-BY https://creativecommons.org/licenses/by/2.0/
Alle weiteren Screenshots wurden von Ralf Eggert erstellt.
46 / 46