Greetings to all readers. Now there are so many trends in web development that you will not follow. But the question of real-time interaction with users of the site is urgent to read for any project. The easiest way is to install one of the widely available open comet-servers, for example, Dklab_Realplexor, Socket.IO or Faye - which one likes or depends on the stack of technologies. True, this is a way of fairly complex projects where a team can afford such a solution.
For many projects, it is simpler (although it is always a question of the specifics of the application) that it will be logical to use third-party solutions. And it is simpler to rent a comet-server functionality as a service. Today there is no shortage of such services, so we have something to review.
And so, first, let's briefly review the existing push-services that allow us to maintain real-time communication between project clients without creating and maintaining our server infrastructure.
')
There are only 6 such services:
Pusher ,
Pubnub ,
Partcl ,
BeaconPush ,
X-Stream.ly and
ioBridge (with some features). Under the cat - a brief overview of all services, features of PHP libraries for them and a description of the library pushBridge.IO for unification of work with all cloud push-services.
Pusher.com
The most famous of these services. At the same time and one of the most difficult because of the abundance of opportunities. In general terms, communication is divided into channels, within which there are user events that client code (javascript) is subscribed to. In addition, there are a number of system events, as well as a system of statuses and alerts and connections / disconnections of other channel users. It is also possible to work with private channels, so that even a connected user, but not knowing a code identifier, will not receive events.
To interact with other systems, Pusher uses the REST-HTTP-API (as well as all similar services), and provides a number of ready-made libraries for 11 languages, including Clojure, Groovy and ColdFusion. I was only interested in PHP API, which is represented by 4 plugins - for Kohana, Code Igniter and bundle for Simfony 2 frameworks, as well as one independent class (
http://github.com/squeeks/Pusher-PHP ). It requires cURL and json extensions to work, and sha256 as a hashing algorithm.
As a note, I’ll say that it was from this service that the idea of ​​my library arose. I will be honest - for one project I needed realtime, and in the test version I didn’t want to write my server, so in a couple of minutes I thought to connect a pusher, especially since I already had an account. It turned out that with all the merits and abundance of documentation, the system is not so simple, and not all the points are well described there. debug mode was very helpful, when the site in the console section displays all your requests sent via the API in real time. But somewhere I stepped and although requests were sent, they did not reach the client. At this place, after an hour of debugging, I abandoned this case. I didn’t like the prospect of rewriting the code at all, besides, in the final version of my project I would still have to switch to my own server. So the idea came up - why should we rewrite everything every time, if you can try to put everything into one unified interface. Looking ahead, I will say that the idea has successfully found its realization!
PubNub.com
This service is simpler and, in this, I see its advantage. The API is extremely simple - there are channels, there are messages in them and that's it. The data format is, of course, JSON everywhere. Both in the client side and on the server side, Pubnub has the widest coverage, providing access to the service on any platform and programming language. The simplicity and powerful support of all platforms makes this service the most interesting of those considered, especially if you need to provide real-time everywhere and everywhere.
The PHP library for accessing the service is quite simple; it allows both sending and receiving messages based on cURL. It works on both 5.2 and 5.3 versions of PHP, allowing you to use buns like callback functions. After examining the source code, a big question remains - for some reason, when sending, after conversion to JSON, the message length should not exceed 1800 characters! What this restriction is connected with is not yet clear, I will contact the developers and find out.
Partcl.com
A fairly new service in this market, initially focused on embedding updated real-time tags on a web page. Currently, the API there is quite expanded and allows you to get a history of changes in values, to build graphs, also working in real time, etc. Unlike other services, positioned only as communication, Partcl works as a content provider, saving all messages and data, which is a rather unique function. Expanding some of the details, I will say that the server part is written in Node.JS + Redis (it is real-time “distributor” - I am its direct developer), and the web part is in Zend Framework.
Although the system has already written an API for PHP, and even a plugin for integration into Wordpress, it was, by my standards, quite primitive and could well not work on some hosts. So I also tried to write a new library implementation for partcl. It turned out even better than the original.
BeaconPush.com
A little-known service, but the only one that offers a dedicated server for demanding clients (the system, by the way, is written in Java). And so, it is normal, though, in addition to channels and messages, it also brings the user’s abstraction to the top, simplifying the communication between specific connected clients. In addition, an interesting functionality of web-hooks, when the service itself pulls the URL you specified, signaling about the input / output of users from the channel. It is also possible to manage the possibilities of publications - if you do not enable it, anyone knowing the public ID will be able to publish data, otherwise only having a secret key.
But with the PHP API, this service did not work out at all. Of course, it is (
https://github.com/ImDom/BeaconPush-PHP and even a module for Code Igniter), but the quality ... is very far from good. By the way, the author of the module sewed your account into the source. Honestly trying to use a ready-made module, but I could not configure it to work properly (stupidly refused to accept my account ID), I completely rewrote its API under Zend_Http.
X-Stream.ly
One more almost unknown service, however possessing a number of interesting counters. For example, you can create special keys to regulate access of specific users to the API (apparently due to the business model). Also, it is the only one, except for Partcl, that has the functionality of persistent message storage. Other features are more or less standard - channels, events, private channels with password access, user statuses. A unique feature is a twitter feed, when the service itself will connect to the specified Twitter account and broadcast new messages to all connected users. On the event of the appearance of messages in the channel, you can put kalbeky, which can also be controlled through the REST-API. By the way, this service is the only one who requires the HTTP authorization to use for the publication (and generally access) to his HTTP API, except for the ID and the secret key, using the login and password of your account, as well as work only through an SSL connection, which makes additional hosting requirements.
The server's native server API is more than scant - C #, Ruby and Node.JS. I had to implement a part of their API from scratch, so here I am the first to write the library.
ioBridge.com
The most interesting and strange service, not quite even push. It is focused on connecting to the web all sorts of hardware (controllers and boards), and also provides data display, collection and storage, and of management via the web. There is also no native client on PHP, there are several suggestions and code sketches in the official forum, but they are far from quality implementation. Yes, and I understood why, starting to do it myself - the service is very strange in places, for example, to get the widget's actionId and session id, you need to make a request to their server, which immediately returns a piece of HTML + JavaScript, from which you have to retrieve data using stupid parsing of lines , which are then needed to connect and send commands. Unfortunately, I could not advance further than the base code, apparently, for full testing it is necessary to connect the device itself. So this code is not tested in real conditions, if anyone has experience with the service, I will be grateful for the tips and all possible help.
And now about the most important thing - pushBridge.IO PHP Library
My library for PHP is designed to replace all native libraries to access each of these services, provides a single and common interface to the basic functionality, while retaining the ability to work directly with the original library (for those cases when it is). For some services, this is the first or, I do not feel shame, the best library (at least in PHP).
So far, only the basic functionality has been implemented - connection and authorization, where required, and sending a message to the specified channel or generating a custom event. All other specific functions can be obtained directly from an instance of the connection class. In the next version, this will also be rewritten to not depend on other people's libraries and provide a single interface for all operations (retrieving the number of connected users, message history, reading messages, etc.).
The library is divided into two parts - the base class is responsible for initializing the necessary adapter, processes the message, and if necessary, serializes it. For this, I used the Zend_Serializer class, so all its formats are supported - from regular Json to exotic Wddx.
The adapter class is responsible for working with specific services, which, if necessary, includes the native library. So far, native classes are used only for Pusher and PubNub, due to the fact that the services provide their specific functions that have not yet been migrated. But after initialization, you can always continue to work directly by simply calling the getConnection () method.
I also tried to somehow unify the data for authorization. Some services use app_id and a secret key, others call them publish and subscribe / public keys, etc. Therefore, I tried to reduce them to the minimum set and save one name for all services:
- appId - usually this is the application ID or API key, the unique identifier of the account or application
- authKey - the secret key that gives the right to publish data
- secretKey - password or other secret key for access to the account
- readKey - the public key for connecting as a client and reading data
- emailKey - username in the form of e-mail (for now it is exclusively for x-Stream.ly)
Three lines are enough to work with the library:
1. Initialization and connection.
$push = new pushBridge_IO( [ Adapter ], [serializer] );
The first parameter is the adapter instance for the service you need, for example:
new pushBridge_Adapter_Pusher(Array('appId' => 'Your app Id', 'authKey' => 'Your key', 'secretKey' => 'Your secret key', 'debug' => true));
Usually, it is enough only data for authorization, the set of which is specific to the service. But the library, unlike its native classes, allows you to flexibly control connection methods using the Zend_Http network stack. For requests, you can use cURL, directly sockets or an adapter to work through a proxy. By default, cURL is used, but if you need, pass the name of the adapter as the httpAdapter parameter, and any of its settings in the httpAdapterConfig according to the ZF documentation (
for example, here ). I repent that at this moment there is still a bug in the current implementation of the library, while the options specified by the user for the adapter are not used, this will be fixed in the next version (the other day).
Since different services require (or vice versa) different methods, you can specify in the method parameter how the adapter will connect to the server. This is usually GET, but sometimes services only understand POST. The adapter takes this into account, but you can override this parameter.
The library inserts its custom header into the request, X-Powered-By, identifying itself, if you wish, you can disable it to save network traffic or just from the principle.
The second parameter is the serializer that will process the message. All services accept either JSON, or (some, for example, Partcl) just a string, without conversion. Initially there is json using the Zend_Serializer class, however you can override with any other. It is enough to pass either the string with the name of the serializer as the second parameter (we currently support: json, php and pickle) or immediately an instance of the Zend_Serializer class with the options you need.
Examples:
Partcl:
$push = new pushBridge_IO( new pushBridge_Adapter_Partcl(Array('secretKey' => 'Your secret key')) );
Pusher:
$push = new pushBridge_IO( new pushBridge_Adapter_Pusher(Array('appId' => 'Your app Id', 'authKey' => 'Your key', 'secretKey' => 'Your secret key', 'debug' => true)) );
Pubnub:
$push = new pushBridge_IO( new pushBridge_Adapter_Pubnub(Array('readKey' => 'Your subscribe key', 'authKey' => 'Your publish key', 'secretKey' => ' Your secret key')) );
BeaconPush:
$push = new pushBridge_IO( new pushBridge_Adapter_Beaconpush(Array('authKey' => 'Your API Key', 'secretKey' => 'Your secret key')) );
And as an example with a custom serializer:
$push = new pushBridge_IO( new pushBridge_Adapter_Partcl(Array('secretKey' => ' Your secret key')), 'php' );
or
$push = new pushBridge_IO( new pushBridge_Adapter_Partcl(Array('secretKey' => 'Your secret key')), Zend_Serializer::factory('Wddx', Array('comment' => 'Powered by ZF+pushBridge.IO') );
2. Just send a message.
In fact, everything is not so simple. Services work very differently with messages. The simplest is the channel-> message model (or the tag -> message), while others introduce a new level - the channel -> event -> message. However, only partcl is very tolerant of the content of the message, for it is just a string, and its understanding is shifted completely to the client. Others require special wrapping of messages in a json structure. None of the services supports mass sending of messages, when in one request it would be possible to publish data in different channels or several different messages and events in one channel. We have already taken into account this moment and in the next version of our service Partcl.com such an opportunity will appear in parallel in the library and emulation of this functionality for everyone else (for the sake of fairness, this functionality is implemented in the class for BeaconPush, but not ported to my library ).
The general dispatch method is as follows:
$push->send( '', 'channel', 'config' );
An already converted string falls into the adapter method, so that it is guaranteed to receive data and it is something more than an empty string. However, if the service requires it, the adapter will form the necessary Json structure over the message data.
If the service uses channels, the second parameter is the string (or array) of channels to which the message should be sent. if there are no channels, this is a tag id or another id.
If you need to set an event code, you should use the config - the third parameter is always an array. The event is set in the event parameter. Additionally, you can disable serialization by passing the parameter serialize = false. If the service accepts, you can specify additional message parameters, for example, the save data flag for X-Stream.ly or enable / disable the debug mode for the message in Pusher.
An example of sending a simple message:
Partcl:
$push->send('Hello world from pushBridge.IO', 'Your tag id', Array('serialize' => false));
Pusher:
$push->send('Hello world from pushBridge.IO', 'test_channel', Array('serialize' => false, 'event' => 'push_test', 'debug' => true));
Pubnub:
$push->send('Hello world from pushBridge.IO', 'my_channel');
x-Stream.ly:
$push->send('Hello world from pushBridge.IO', 'mychannel', Array('event' => 'my_event', 'persisted' => true));
Of course, by default, the maximum parameters are set so that there is no need to specify something, often even the name of the channel or event is set as they are assigned by the service after registration. But for a more complete understanding of the options, you should refer to the documentation for a particular service.
Library source code and brief examples:
github.com/aleksraiden/pushBridge.IO/tree/ServiceWrapperThe plans for the next release: error correction, unification of the send method, support for publishing several variables at once, the implementation of the data reading method, as well as raising the project site on the
pushcloudapi.com domain. I would be grateful for comments and additions.