This article is part of the article "PEIP - Why to create an Event Driven Messaging Framework?". (to be published)
Traditionally Service Oriented Architecture is associated mainly with Programming
Languages such as Java, C# or C++. This deriving from the fact that most business
applications are written in these Languages and business applications may have the
need to interact oder transfer data. In a heterogeneous business architectures the
need for service orientation is inherent. SOA in this case is a way to decouple
dependencies and APIs between business or enterprise application.
PHP is rarely associated with enterprise or business architecture nor with Service Oriented
Architecture generally. Does this mean that PHP applications do not face the need for
services orientation at all?
The answer (at least since this millennium) is NO!
Modern PHP applications have to deal with a lot of different types of services may they
be web services or inline server or PHP services.
Web services can include interacting with a social network, fetching data from a
remote source, informations about a successful customer payment and a lot more.
Thus web services meaning any interaction with a source on another server regardless
of the used protocol.
Inline services on the server can include exchanging data with a cache or indexing
engine like as Memcached or Solr, interacting with chat application or a comet/push
server like as APE and of course any manipulation on databases may it be a relational
db like MySQL or Oracle, a document-oriented one like CouchDB or a native XML-DB
as for example eXist.
Inline PHP services can include custom made service classes/objects, interaction between
different web applications, providing a web API for a remote consumer as an AJAX or
mobile application or out-sourcing heavy tasks to a Gearman worker (what actually
would fit in the last category, if not a worker could be written in PHP).
Service as used in PEIP does mean any arbitrary object instance which may can be
manipulated before calling a certain method on it, hence it´d fit with any of your
typically used objects. (In Java-land service in this case would refer to a bean, but
since we are talking about PHP-land there are no beans - you could call them Peas
if you like.)
Despite on that, solutions to deal with Service Oriented Architecture in a homogeneous
way in PHP are rare. To be named is mainly the SOA PHP project with the PHP extensions
SDO (Service Data Objects) and SCA (Service Component Architecture), the last one
as for now being marked as experimental. Nevertheless for both will be written an
extension for PEIP (While you can allready use them with PEIP). An extension because
it will of cause depend on one or both of this PHP extension to be installed and loaded.
If you do not count the PHP extensions which cope with different web service protocols,
that´s about it. As far as you can trust a google search there is no solution entirely written
in PHP, while there are plenty of articles about it.
Monday, March 15. 2010
How to implement a secure push to APE (Ajax Push Engine)
APE (Ajax Push Engine) is an extraodinary Client/Server Framework for creating
AJAX PUSH (aka Comet) Applications. In the latest revisions on github there is
even the use of HTML5´s Websockets implemented, which makes the
standard way of implementing Comet by using a "hanging iframe" obsolete
(for browsers with websocket support). Also the APE server can be scripted by
using JavaScript which makes it very easy to extend it´s features (at least for
developers with JS knowledge). The default framework used is mootools, but any
other or plain JS could do the same.
One of APE´s nice features is to invoke messages to the client
by a script or application on the server side or even on a different
server. This is very usefull when you want to broadcast certain server
events or messages from other applications to the Clients connected to APE.
They way how to do this is is register a certain server command, which then
excutes the appropriate logic. The command then can be called by the invoking
script through HTTP (Depending on your needs a socket connection would also be
possible). In APE´s demo section an example for such a feature can be found in
the "Controller" Demo using a simple PHP script. (If you need an OOP style Client Library
to connect to APE through PHP you may want to check my APE_PHP on github)
However in the Controller demo every message sent by the external script is
broadcasted to every user connected to the certain channel. While this is usefull
for a lot of cases, there might be the need to send a message to only one
specific user on the channel. There is a simple solution for this problem:
One could use a different channel per user and send the message through it.
But this approach has (at least) two drawbacks. One is scalability, the other is
security. Since the way this is done could be easily found out on the server side
a "bad user" could connect to the other user´s channel and receive all of his
private messages. This post has been inspired by a discussion on APE´s mailing
list on how to implement such feature in a secure way.
In this scenario we assume that there is some kind of server side authentification
process (It wouldn`t make much sense otherwise anymway) . So when the user
is authenticated a secret key is generated or the session key or simething else is
used. This key will be send to the client with the page where the APE connection
will be established.
On the server side we create a hook for the "connect" command and register
the key as a private property on the user object.
Now we create our custom APE command to be called from the script:
The Client then connects to APE using the special key:
Now we can send a message (with the secret key)through our script to the
user and only he will receive our message (Example in PHP):
This is the most simple solution on how to do secure pushs to APE. However it
still has (atleast) one drawback, that it uses "channel.userslist.each(function(user){[...]});"
which doesn´t scale with a lot of users. I hope I will have the time to post a solution
using a proper registry and a way to reconnect with usernames (the default would response
with "NICK_USED" if a client would refresh the page).
AJAX PUSH (aka Comet) Applications. In the latest revisions on github there is
even the use of HTML5´s Websockets implemented, which makes the
standard way of implementing Comet by using a "hanging iframe" obsolete
(for browsers with websocket support). Also the APE server can be scripted by
using JavaScript which makes it very easy to extend it´s features (at least for
developers with JS knowledge). The default framework used is mootools, but any
other or plain JS could do the same.
One of APE´s nice features is to invoke messages to the client
by a script or application on the server side or even on a different
server. This is very usefull when you want to broadcast certain server
events or messages from other applications to the Clients connected to APE.
They way how to do this is is register a certain server command, which then
excutes the appropriate logic. The command then can be called by the invoking
script through HTTP (Depending on your needs a socket connection would also be
possible). In APE´s demo section an example for such a feature can be found in
the "Controller" Demo using a simple PHP script. (If you need an OOP style Client Library
to connect to APE through PHP you may want to check my APE_PHP on github)
However in the Controller demo every message sent by the external script is
broadcasted to every user connected to the certain channel. While this is usefull
for a lot of cases, there might be the need to send a message to only one
specific user on the channel. There is a simple solution for this problem:
One could use a different channel per user and send the message through it.
But this approach has (at least) two drawbacks. One is scalability, the other is
security. Since the way this is done could be easily found out on the server side
a "bad user" could connect to the other user´s channel and receive all of his
private messages. This post has been inspired by a discussion on APE´s mailing
list on how to implement such feature in a secure way.
In this scenario we assume that there is some kind of server side authentification
process (It wouldn`t make much sense otherwise anymway) . So when the user
is authenticated a secret key is generated or the session key or simething else is
used. This key will be send to the client with the page where the APE connection
will be established.
On the server side we create a hook for the "connect" command and register
the key as a private property on the user object.
- Ape.registerHookCmd("connect", function(params, cmd) {
- // this makes the key a private property on the user object
- cmd.user.key = params.key
- return 1;
- });
Now we create our custom APE command to be called from the script:
- Ape.registerCmd("securepush", false, function(params, infos) {
- if (params.password == "foobar") {
- if ($defined(params.channel) && $defined(params.key)){
- var channel = Ape.getChannelByName(params.channel);
- if (!$defined(channel)) return ["401", "UNKNOWN_CHANNEL"];
- var sent = false;
- channel.userslist.each(function(user){
- if(user.key == params.key){
- user.pipe.sendRaw(params.raw, params.data);
- sent = true;
- }
- });
- return sent ? {"name":"pushed","data":{"value":"ok"}} : ["400", "USER_NOT_FOUND"];
- }
- return ["400", "BAD_KEY"];
- } else {
- return ["400", "BAD_PASSWORD"];
- }
- });
- var client = new APE.Client();
- client.load();
- client.addEvent('load', function() {
- client.core.start({"name": 'UserName', "key":"secretKey"});
- client.addEvent('ready', function() {
- client.core.join('SecureChannel');
- }
- });
user and only he will receive our message (Example in PHP):
- $APEserver = 'http://ape.example.com:6969/?';
- $APEPassword = 'foobar';
- 'cmd' => 'securepush',
- 'password' => $APEPassword,
- 'raw' => 'postmsg',
- 'channel' => 'SecureChannel',
- 'key' => 'secretKey',
- 'message' => 'You have a new message!'
- )
- )
- ));
- if ($res->data->value == 'ok') {
- echo '<br />Message sent! result: ';
- } else {
- echo 'Error sending message, server response is : ';
- }
This is the most simple solution on how to do secure pushs to APE. However it
still has (atleast) one drawback, that it uses "channel.userslist.each(function(user){[...]});"
which doesn´t scale with a lot of users. I hope I will have the time to post a solution
using a proper registry and a way to reconnect with usernames (the default would response
with "NICK_USED" if a client would refresh the page).
Sunday, February 28. 2010
How to implement an Sealer/Unsealer Pattern in PHP
The Sealer/Unsealer Pattern serves in your code when you want
to pass somewhere a reference to a value but not the value itself.
You pass the the Sealer your certain value and it will return a sort
of key for it - called box. Now only with that box you will be able to
retrieve the initial value from the Unsealer.
An Interface for a Sealer might look like this:
An Interface for a Unsealer might look like this:
Now for our implementation of the Sealer/Unsealer Pattern we keep things simple
and put both in the same class. This is a PHP5 < 5.3 variant:
Since PHP5.3 there is a much shorter and more elegant way to implment the
Sealer/Unsealer Pattern. The newly introduced SplObjectStorage class is similar to a Store, Map or Hash but it uses Objects as the key. In other words you can store an arbitrary value in it and reference it with an object.
The above implementation uses Dependency Injection in the constructor to may inject a certain instance of SplObjectStorage or from a subclass - however this is (certainly) not part of the Sealer/Unsealer Pattern.
Now to use the Sealer/Unsealer class you could do something like this:
You may have noticed that both Sealer/Unsealer classes above have a second argument.
This second argument lets you pass in a certain Object to use as the box for the value.
In other words you can use any arbitrary object as the key for the Sealer/Unsealer:
There are far more sophisticated implementations of the Sealer/Unsealer Pattern which
use cryptographic methods or even public/private keys - However the above should give a
impression how the Pattern works and how it can be implemented in PHP - Additionally it
shows a good use of PHP´s new native SplObjectStorage class.
to pass somewhere a reference to a value but not the value itself.
You pass the the Sealer your certain value and it will return a sort
of key for it - called box. Now only with that box you will be able to
retrieve the initial value from the Unsealer.
An Interface for a Sealer might look like this:
- interface Sealer {
- public function seal($value);
- }
- interface Unsealer {
- public function unseal($box);
- }
Now for our implementation of the Sealer/Unsealer Pattern we keep things simple
and put both in the same class. This is a PHP5 < 5.3 variant:
- class SealerUnsealer implements Sealer, Unsealer{
- protected
- public function seal($value, $box = false){
- $box = (bool)$box ? $box : new stdClass;
- $this->values[$c] = $value;
- $this->boxes[$c] = $box;
- }
- public function unseal($box){
- foreach($this->boxes as $k=>$b) {
- if($b === $box){
- return $this->values[$k];
- }
- }
- }
- }
Sealer/Unsealer Pattern. The newly introduced SplObjectStorage class is similar to a Store, Map or Hash but it uses Objects as the key. In other words you can store an arbitrary value in it and reference it with an object.
- class SealerUnsealer implements Sealer, Unsealer {
- protected $store;
- public function __construct(SplObjectStorage $store = false){
- $this->store = (bool)$store ? $store : new SplObjectStorage;
- }
- public function seal($value, $box = false){
- $box = (bool)$box ? $box : new stdClass;
- $this->store[$box] = $value;
- return $box;
- }
- public function unseal($box){
- return $this->store[$box];
- }
- }
Now to use the Sealer/Unsealer class you could do something like this:
- $sealer = new SealerUnsealer();
- $message = 'My Secret Message'
- $box = $sealer->seal($message);
- echo $sealer->unseal($box);
- // My Secret Message
You may have noticed that both Sealer/Unsealer classes above have a second argument.
This second argument lets you pass in a certain Object to use as the box for the value.
In other words you can use any arbitrary object as the key for the Sealer/Unsealer:
- $object = new MyObject();
- $sealer = new SealerUnsealer();
- $message = 'My Secret Message'
- $sealer->seal($message, $object);
- echo $sealer->unseal($object);
- // My Secret Message
There are far more sophisticated implementations of the Sealer/Unsealer Pattern which
use cryptographic methods or even public/private keys - However the above should give a
impression how the Pattern works and how it can be implemented in PHP - Additionally it
shows a good use of PHP´s new native SplObjectStorage class.
Tuesday, February 23. 2010
How to call a PHP constructor like call_user_func_array
PHP´s native function call_user_func_array comes in very handy when dynamically calling a
callable (instance-method, static-method, function, lamdba/closure) with an arbitrary number of arguments.
However this function has one drawback since it doesnt support the creation of an object
through its class´ constructor.
The following code will not construct a new TestClass2 instance, but result in a warning:
"call_user_func_array() expects parameter 1 to be a valid callback, non-static method
TestClass2::__construct() cannot be called statically in [...]"
Luckily there are some solutions to this problem:
The "nasty, ugly and evil approach"
This solution is definitely not recommended (at least when you are on PHP5 or higher),
since it relies on the execution of dynamically created code through the 'eval' function.
This is not safe nor reliable, however it´s the only way to do the magic in PHP4.
The "Reflection approach"
Luckily PHP5 introduced back then the Reflection set of classes, which can be used to
examine and reverse-engineer classes, functions, methods, etc. Additionally the Reflection
classes provide delegate methods to call on methods or functions.
In this (recommended) approach, we use 'newInstanceArgs' method of ReflectionClass,
which gives us a clean and reliable way to construct objects dynamically.
The "polymorphic approach"
This last solution is just a variation of the "Reflection approach", but it serves in places
where a (building) part of application should not be aware of wether it´s calling a native
constructor or an arbitrary method ('build', 'getInstance', etc.). For the latter we have to
use call_user_func_array in any way and it´s very simple to make the "Reflection approach"
work in the same way.
callable (instance-method, static-method, function, lamdba/closure) with an arbitrary number of arguments.
- class TestClass1 {
- public static function argsToArray($arg1, $arg2, $arg3){
- }
- }
- // array(1,2,3)
However this function has one drawback since it doesnt support the creation of an object
through its class´ constructor.
The following code will not construct a new TestClass2 instance, but result in a warning:
"call_user_func_array() expects parameter 1 to be a valid callback, non-static method
TestClass2::__construct() cannot be called statically in [...]"
- class TestClass2 {
- public function __construct($arg1, $arg2, $arg3){
- [...]
- }
- }
- // null
Luckily there are some solutions to this problem:
The "nasty, ugly and evil approach"
This solution is definitely not recommended (at least when you are on PHP5 or higher),
since it relies on the execution of dynamically created code through the 'eval' function.
This is not safe nor reliable, however it´s the only way to do the magic in PHP4.
- class TestClass3 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- }
- function call_constructor_array_eval($cls, $arguments){
- return $obj;
- }
- // object(TestClass3)[1]
- // public 'arg1' => int 1
- // public 'arg2' => int 2
- // public 'arg3' => int 3
The "Reflection approach"
Luckily PHP5 introduced back then the Reflection set of classes, which can be used to
examine and reverse-engineer classes, functions, methods, etc. Additionally the Reflection
classes provide delegate methods to call on methods or functions.
In this (recommended) approach, we use 'newInstanceArgs' method of ReflectionClass,
which gives us a clean and reliable way to construct objects dynamically.
- class TestClass4 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- }
- function call_constructor_array_reflection($cls, $arguments){
- $rc = new ReflectionClass('TestClass');
- return $rc->newInstanceArgs($arguments);
- }
- // object(TestClass4)[1]
- // public 'arg1' => int 7
- // public 'arg2' => int 8
- // public 'arg3' => int 9
The "polymorphic approach"
This last solution is just a variation of the "Reflection approach", but it serves in places
where a (building) part of application should not be aware of wether it´s calling a native
constructor or an arbitrary method ('build', 'getInstance', etc.). For the latter we have to
use call_user_func_array in any way and it´s very simple to make the "Reflection approach"
work in the same way.
- class TestClass5 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- public function argsToArray($arg1, $arg2, $arg3){
- }
- }
- $rc = new ReflectionClass('TestClass5');
- // object(TestClass5)[1]
- // public 'arg1' => string 'a' (length=1)
- // public 'arg2' => string 'b' (length=1)
- // public 'arg3' => string 'c' (length=1)
- //array
- // 0 => string 'x' (length=1)
- // 1 => string 'y' (length=1)
- // 2 => string 'z' (length=1)
Saturday, February 13. 2010
Pearfarm - Php community's pear hosting service
Pearfarm seems to be a a good approach for a community hosting of "PEARish" Packages.
The procedure of publishing an official PEAR-Package can be time consuming and cumbersome. You have to go from a draft (not necessarily) of the package over a proposal till the final release (If you get enough positive votes from PEAR members).
Also you have respect the PEAR-specific coding-guidelines. While coding-guidelines per se are positive,
not everybody may likes to format their code in PEAR-way.
On the other hand maintaining a own PEAR-Server is not suitable for anyone. The Chiara-PEAR-Server-Project (existing since 2006 and a long time not releasing a new version) is still in beta (since 12/2008)
and I never managed to get a working package-copy by using the PEAR-Installer.
Now Pearfarm is an independent (from PEAR) project
which aims at the problems mentioned above. It comes with an PEAR-Package for creating, maintaining
and uploading your PEARish Packages to Pearfarm.
While the project is relatively young, existing since Dec 2009, we will see what´s happening and if
the community is taking over this new PEAR space. I will give it a try!
P.S.:
Pirum is also a new and good approach to create a (self hosted) PAER server.
The project has been created by symfony`s master mind Fabien Potencier.
The procedure of publishing an official PEAR-Package can be time consuming and cumbersome. You have to go from a draft (not necessarily) of the package over a proposal till the final release (If you get enough positive votes from PEAR members).
Also you have respect the PEAR-specific coding-guidelines. While coding-guidelines per se are positive,
not everybody may likes to format their code in PEAR-way.
On the other hand maintaining a own PEAR-Server is not suitable for anyone. The Chiara-PEAR-Server-Project (existing since 2006 and a long time not releasing a new version) is still in beta (since 12/2008)
and I never managed to get a working package-copy by using the PEAR-Installer.
Now Pearfarm is an independent (from PEAR) project
which aims at the problems mentioned above. It comes with an PEAR-Package for creating, maintaining
and uploading your PEARish Packages to Pearfarm.
While the project is relatively young, existing since Dec 2009, we will see what´s happening and if
the community is taking over this new PEAR space. I will give it a try!
P.S.:
Pirum is also a new and good approach to create a (self hosted) PAER server.
The project has been created by symfony`s master mind Fabien Potencier.
(Page 1 of 1, totaling 5 entries)

