用于与 Pusher Channels HTTP API 交互的 PHP 库。
在 https://pusher.com 注册并在您的应用程序中使用应用程序凭据,如下所示。
如需报告问题、错误和功能请求,请随时提出拉取请求或提出问题。如果您没有收到及时回复,请随时查看我们的支持门户。
您可以通过名为pusher-php-server
Composer 包获取 Pusher Channels PHP 库。请参阅 https://packagist.org/packages/pusher/pusher-php-server
$ composer require pusher/pusher-php-server
或者添加到composer.json
:
"require" : {
"pusher/pusher-php-server" : " ^7.2 "
}
然后运行composer update
。
使用 Pusher Channels 应用程序中的凭据创建新的PusherPusher
实例。
$ app_id = ' YOUR_APP_ID ' ;
$ app_key = ' YOUR_APP_KEY ' ;
$ app_secret = ' YOUR_APP_SECRET ' ;
$ app_cluster = ' YOUR_APP_CLUSTER ' ;
$ pusher = new Pusher Pusher ( $ app_key , $ app_secret , $ app_id , [ ' cluster ' => $ app_cluster ]);
第四个参数是$options
数组。附加选项有:
scheme
- 例如 http 或 httpshost
- 主机,例如 api.pusherapp.com。没有尾随正斜杠port
- http 端口path
- 附加到所有请求路径的前缀。仅当您针对自己控制的端点(例如,基于路径前缀进行路由的代理)运行库时,这才有用。timeout
- HTTP 超时useTLS
- 使用 https 和端口 443 方案的快速选项。cluster
- 指定运行应用程序的集群。encryption_master_key_base64
- 32 个字符长的密钥。该密钥与通道名称一起用于派生每个通道的加密密钥。每通道密钥用于加密加密通道上的事件数据。例如,默认情况下将通过 HTTPS 进行调用。要使用纯 HTTP,您可以将 useTLS 设置为 false:
$ options = [
' cluster ' => $ app_cluster ,
' useTLS ' => false
];
$ pusher = new Pusher Pusher ( $ app_key , $ app_secret , $ app_id , $ options );
推荐的日志记录方法是使用实现PsrLogLoggerInterface
PSR-3 兼容记录器。 Pusher
对象实现PsrLogLoggerAwareInterface
,这意味着您可以调用setLogger(LoggerInterface $logger)
来设置记录器实例。
// where $logger implements `LoggerInterface`
$ pusher -> setLogger ( $ logger );
该库在内部使用 Guzzle 进行 HTTP 调用。您可以将自己的 Guzzle 实例传递给 Pusher 构造函数:
$ custom_client = new GuzzleHttp Client ();
$ pusher = new Pusher Pusher (
$ app_key ,
$ app_secret ,
$ app_id ,
[],
$ custom_client
);
这允许您传递自己的中间件,请参阅测试示例。
要在一个或多个通道上触发事件,请使用trigger
功能。
$ pusher -> trigger ( ' my-channel ' , ' my_event ' , ' hello world ' );
$ pusher -> trigger ([ ' channel-1 ' , ' channel-2 ' ], ' my_event ' , ' hello world ' );
还可以通过单个 API 调用发送多个事件(多租户集群上每次调用最多 10 个事件):
$ batch = [];
$ batch [] = [ ' channel ' => ' my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' hello ' => ' world ' ]];
$ batch [] = [ ' channel ' => ' my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' myname ' => ' bob ' ]];
$ pusher -> triggerBatch ( $ batch );
trigger
和triggerBatch
在triggerAsync
和triggerBatchAsync
中都有异步对应项。这些函数返回 Guzzle 承诺,可以与->then
链接:
$ promise = $ pusher -> triggerAsync ([ ' channel-1 ' , ' channel-2 ' ], ' my_event ' , ' hello world ' );
$ promise -> then ( function ( $ result ) {
// do something with $result
return $ result ;
});
$ final_result = $ promise -> wait ();
数组会自动转换为 JSON 格式:
$ array [ ' name ' ] = ' joe ' ;
$ array [ ' message_count ' ] = 23 ;
$ pusher -> trigger ( ' my_channel ' , ' my_event ' , $ array );
其输出将是:
" {'name': 'joe', 'message_count': 23} "
为了避免重复,您可以选择在触发事件时指定发送者的套接字 ID:
$ pusher -> trigger ( ' my-channel ' , ' event ' , ' data ' , [ ' socket_id ' => $ socket_id ]);
$ batch = [];
$ batch [] = [ ' channel ' => ' my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' hello ' => ' world ' ], [ ' socket_id ' => $ socket_id ]];
$ batch [] = [ ' channel ' => ' my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' myname ' => ' bob ' ], [ ' socket_id ' => $ socket_id ]];
$ pusher -> triggerBatch ( $ batch );
可以使用info
参数请求有关已发布到的通道的属性:
$ result = $ pusher -> trigger ( ' my-channel ' , ' my_event ' , ' hello world ' , [ ' info ' => ' subscription_count ' ]);
$ subscription_count = $ result -> channels [ ' my-channel ' ]-> subscription_count ;
$ batch = [];
$ batch [] = [ ' channel ' => ' my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' hello ' => ' world ' ], ' info ' => ' subscription_count ' ];
$ batch [] = [ ' channel ' => ' presence-my-channel ' , ' name ' => ' my_event ' , ' data ' => [ ' myname ' => ' bob ' ], ' info ' => ' user_count,subscription_count ' ];
$ result = $ pusher -> triggerBatch ( $ batch );
foreach ( $ result -> batch as $ i => $ attributes ) {
echo " channel: { $ batch [ $ i ][ ' channel ' ]} , name: { $ batch [ $ i ][ ' name ' ]}" ;
if ( isset ( $ attributes -> subscription_count )) {
echo " , subscription_count: { $ attributes -> subscription_count }" ;
}
if ( isset ( $ attributes -> user_count )) {
echo " , user_count: { $ attributes -> user_count }" ;
}
echo PHP_EOL ;
}
如果您的数据已经以 JSON 格式编码,您可以通过将第六个参数设置为 true 来避免第二个编码步骤,如下所示:
$ pusher -> trigger ( ' my-channel ' , ' event ' , ' data ' , [], true );
要对应用程序上的 Pusher Channels 上的用户进行身份验证,您可以使用authenticateUser
函数:
$ pusher -> authenticateUser ( ' socket_id ' , ' user-id ' );
有关详细信息,请参阅验证用户身份。
要授权您的用户访问 Pusher 上的私人频道,您可以使用authorizeChannel
函数:
$ pusher -> authorizeChannel ( ' private-my-channel ' , ' socket_id ' );
有关详细信息,请参阅授权用户。
使用状态通道与专用通道类似,但您可以指定额外的数据来识别该特定用户:
$ pusher -> authorizePresenceChannel ( ' presence-my-channel ' , ' socket_id ' , ' user_id ' , ' user_info ' );
有关详细信息,请参阅授权用户。
该库提供了一种方法来验证您从 Pusher 收到的 Webhook 是否确实是来自 Pusher 的正版 Webhook。它还提供了存储它们的结构。称为webhook
的辅助方法可以实现此目的。传入请求的标头和正文,它将返回一个包含已验证事件的 Webhook 对象。如果库无法验证签名,则会抛出异常。
$ webhook = $ pusher -> webhook ( $ request_headers , $ request_body );
$ number_of_events = count ( $ webhook -> get_events ());
$ time_received = $ webhook -> get_time_ms ();
该库支持您的私人频道的端到端加密。这意味着只有您和您连接的客户端才能阅读您的消息。 Pusher 无法解密它们。您可以按照以下步骤启用此功能:
您应该首先设置私人频道。这涉及在您的服务器上创建授权端点。
接下来,生成 32 字节主加密密钥,对其进行 Base64 编码并安全存储。这是秘密,您不应该与任何人分享。连推手也不行。
要从良好的随机源生成适当的密钥,您可以使用openssl
命令:
openssl rand -base64 32
创建 Pusher 客户端时指定主加密密钥:
$ pusher = new Pusher Pusher (
$ app_key ,
$ app_secret ,
$ app_id ,
[
' cluster ' => $ app_cluster ,
' encryption_master_key_base64 ' => " <your base64 encoded master key> "
]
);
您希望使用端到端加密的通道应以private-encrypted-
为前缀。
在您的客户端中订阅这些频道,您就完成了!您可以通过检查 https://dashboard.pusher.com/ 上的调试控制台并查看加扰的密文来验证它是否正常工作。
重要提示:这不会加密没有private-encrypted-
前缀的通道上的消息。
限制:您不能在调用trigger
时在未加密和加密通道的混合上触发单个事件,例如
$ data [ ' name ' ] = ' joe ' ;
$ data [ ' message_count ' ] = 23 ;
$ pusher -> trigger ([ ' channel-1 ' , ' private-encrypted-channel-2 ' ], ' test_event ' , $ data );
基本原理:此库中的方法直接映射到各个 Channels HTTP API 请求。如果我们允许在多个通道(有些是加密的,有些是未加密的)上触发单个事件,那么将需要两个 API 请求:一个是事件被加密到加密通道,另一个是事件未加密到未加密通道。
创建 Pusher 对象时,首先在 JS 应用程序中设置通道授权端点:
var pusher = new Pusher ( "app_key" ,
// ...
channelAuthorization : {
endpoint : "/presenceAuth.php" ,
} ,
) ;
接下来,在presenceAuth.php中创建以下内容:
<?php
header ( ' Content-Type: application/json ' );
if ( isset ( $ _SESSION [ ' user_id ' ])) {
$ stmt = $ pdo -> prepare ( " SELECT * FROM `users` WHERE id = :id " );
$ stmt -> bindValue ( ' :id ' , $ _SESSION [ ' user_id ' ], PDO :: PARAM_INT );
$ stmt -> execute ();
$ user = $ stmt -> fetch ();
} else {
die ( json_encode ( ' no-one is logged in ' ));
}
$ pusher = new Pusher Pusher ( $ key , $ secret , $ app_id );
$ presence_data = [ ' name ' => $ user [ ' name ' ]];
echo $ pusher -> authorizePresenceChannel ( $ _POST [ ' channel_name ' ], $ _POST [ ' socket_id ' ], $ user [ ' id ' ], $ presence_data );
注意:这假设您将用户存储在名为users
表中,并且这些用户具有name
列。它还假设您有一个登录机制,可以将登录用户的user_id
存储在会话中。
$ pusher -> getChannelInfo ( $ name );
还可以从 Channels HTTP API 获取有关通道的信息。
$ info = $ pusher -> getChannelInfo ( ' channel-name ' );
$ channel_occupied = $ info -> occupied ;
对于在线状态频道,您还可以查询当前订阅该频道的不同用户数量(单个用户可能订阅多次,但仅算作一次):
$ info = $ pusher -> getChannelInfo ( ' presence-channel-name ' , [ ' info ' => ' user_count ' ]);
$ user_count = $ info -> user_count ;
如果您启用了查询subscription_count
(当前订阅该频道的连接数)的功能,那么您可以按如下方式查询该值:
$ info = $ pusher -> getChannelInfo ( ' presence-channel-name ' , [ ' info ' => ' subscription_count ' ]);
$ subscription_count = $ info -> subscription_count ;
$ pusher -> getChannels ();
还可以从 Channels HTTP API 获取应用程序的通道列表。
$ result = $ pusher -> getChannels ();
$ channel_count = count ( $ result -> channels ); // $channels is an Array
$ pusher -> getChannels ([ ' filter_by_prefix ' => ' some_filter ' ]);
还可以根据名称前缀获取频道列表。为此,您需要向调用提供$options
参数。在以下示例中,调用将返回带有presence-
前缀的所有频道的列表。这是获取所有在线频道列表的想法。
$ results = $ pusher -> getChannels ([ ' filter_by_prefix ' => ' presence- ' ]);
$ channel_count = count ( $ result -> channels ); // $channels is an Array
这也可以使用通用的pusher->get
函数来实现:
$ pusher -> get ( ' /channels ' , [ ' filter_by_prefix ' => ' presence- ' ]);
返回频道列表的 HTTP API 不支持随每个频道返回订阅计数。相反,您可以通过迭代每个通道并发出另一个请求来获取此数据。请注意:这种方法会消耗(通道数 + 1)条消息!
<?php
$ subscription_counts = [];
foreach ( $ pusher -> getChannels ()-> channels as $ channel => $ v ) {
$ subscription_counts [ $ channel ] =
$ pusher -> getChannelInfo (
$ channel , [ ' info ' => ' subscription_count ' ]
)-> subscription_count ;
}
var_dump ( $ subscription_counts );
$ results = $ pusher -> getPresenceUsers ( ' presence-channel-name ' );
$ users_count = count ( $ results -> users ); // $users is an Array
这也可以使用通用的pusher->get
函数来实现:
$ response = $ pusher -> get ( ' /channels/presence-channel-name/users ' );
$response
的格式为:
Array (
[body] => { " users " :[{ " id " :"a_user_id"}]}
[status] => 200
[result] => Array (
[users] => Array (
[ 0 ] => Array (
[id] => a_user_id
),
/* Additional users */
)
)
)
$ pusher -> get ( $ path , $ params );
用于对 Channels HTTP API 进行GET
查询。处理身份验证。
响应是一个带有result
索引的关联数组。该索引的内容取决于调用的 HTTP 方法。但是,允许 HTTP 状态代码的status
属性始终存在,并且如果状态代码指示成功调用 API,则将设置result
属性。
$ response = $ pusher -> get ( ' /channels ' );
$ http_status_code = $ response [ ' status ' ];
$ result = $ response [ ' result ' ];
需要 phpunit。
composer install
tests
目录config.example.php
重命名为config.php
并将这些值替换为有效的 Channels 凭据或创建环境变量。composer exec phpunit
以运行所有测试。 版权所有 2014,Pusher。根据 MIT 许可证获得许可:https://www.opensource.org/licenses/mit-license.php
版权所有 2010,斯奎克斯。根据 MIT 许可证获得许可:https://www.opensource.org/licenses/mit-license.php