Home / PostsPost
Symfony 中的 Services
嘟噜聪2016/08/14 16:07:00 4117人已阅
简介 两个小例子来说明symfony中如何自写义自己的services,真的非常简单。
Symfony 中的 Services
两个小例子来说明symfony中如何自写义自己的services,真的非常简单。
What is a Service?
官方文档是这么说的:
Put simply, a service is any PHP object that performs some sort of "global" task. It's a purposefully-generic name used in computer science to describe an object that's created for a specific purpose (e.g. delivering emails). Each service is used throughout your application whenever you need the specific functionality it provides. You don't have to do anything special to make a service: simply write a PHP class with some code that accomplishes a specific task. Congratulations, you've just created a service!
大概的意思是: 服务是某种“全局”的PHP对象。它是在计算机科学中用于描述对特定目的(例如提供电子邮件)创建的对象的目的地 - 通用名称。当你需要它提供的特定功能,每个服务在整个应用程序使用。你不必做其他特殊的操作使服务:只需编写一个PHP类,完成特定的任务。
``
创建、配制一个服务
比如我现在有一个生成短链接的类:
// src/AppBundle/Utils/ShortUrl.php
namespace AppBundle\Utils;
/**
* Class ShortUrl
* @package AppBundle\Utils
*/
class ShortUrl
{
/**
* 字符表
*
* @var string
*/
public $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/**
* @param $url
* @param string $baseUrl
* @return array
*/
public function short($url, $baseUrl = '')
{
$key = "alexis";
$urlHash = md5($key . $url);
$len = strlen($urlHash);
$short_url_list = [];
// 将加密后的串分成4段,每段4字节,对每段进行计算,一共可以生成四组短连接
for ($i = 0; $i < 4; $i++) {
$urlHash_piece = substr($urlHash, $i * $len / 4, $len / 4);
// 将分段的位与0x3fffffff做位与,0x3fffffff表示二进制数的30个1,即30位以后的加密串都归零
$hex = hexdec($urlHash_piece) & 0x3fffffff; #此处需要用到hexdec()将16进制字符串转为10进制数值型,否则运算会不正常
// 生成6位短连接
for ($j = 0; $j < 6; $j++) {
// 将得到的值与0x0000003d,3d为61,即charset的坐标最大值
$baseUrl .= $this->charset[$hex & 0x0000003d];
// 循环完以后将hex右移5位
$hex = $hex >> 5;
}
$short_url_list[] = $baseUrl;
}
return $short_url_list;
}
}
那如何使上面这个类成为symfony中的一个服务呢?
下面一个简单的例子来说明:
打开app/config/services.yml
文件在 services
下加入
# app/config/services.yml
services:
app.utils.shortUrl: # 命名推荐使用 {bundle}.{服务名称}
class: AppBundle\Utils\ShortUrl
# arguments: [] # 因为这需要依赖其他服务,所以arguments为空就行了,如果需要注入其他服务的话按官方文档写就行了。
使用这个服务
咱们在 src/AppBundle/Controller/DefaultController.php
文件的 indexAction
方法加入以下代码:
public function indexAction(Request $request)
{
$shareUrl = $this->get('app.utils.shortUrl');
$shorts = $shareUrl->short($this->generateUrl('photo_index', ['sign' => $photo->getUuid()], UrlGeneratorInterface::ABSOLUTE_URL));
dump($shorts[0]); // 它返回的是一个多维数组,下标 0 就是最短的6位
}
来一个需要注入其他服务的例子
先写一个ip的服务
// src/AppBundle/Utils/IP.php
namespace AppBundle\Utils;
/**
* Class IP
* @package AppBundle\Utils
*/
class IP
{
/**
* ip to long
*
* @param string $ip
* @return int
*/
public function ipToLong($ip)
{
return bindec(decbin(ip2long($ip)));
}
/**
* reset ip
*
* @param $decimal
* @return string
*/
public function resetIp($decimal)
{
return long2ip($decimal);
}
/**
* check ip
*
* @param $address
* @return mixed
*/
public function checkIP($address)
{
return filter_var($address, FILTER_VALIDATE_IP);
}
}
再写一个需要注入其他服务的类
// src/AppBundle/Utils/RedisClient.php
namespace AppBundle\Utils;
use AppBundle\Entity\Address;
use Monolog\Logger;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Class RedisClient
* @package AppBundle\Utils
*/
class RedisClient
{
/**
* @var \Redis
*/
private $redis;
/**
* @var IP
*/
private $IP;
/**
* @var Logger
*/
private $logger;
/**
* @var array
*/
private $filter = [
'KEYS', 'GET', 'HGET', 'HGETALL', 'DEL', 'AUTH', 'SORT', 'ZADD', 'SADD', 'LPOP', 'HLEN', 'HMSET', 'TTL', 'TYPE', 'INCR', 'HDEL', 'EXISTS',
'SELECT', 'HEXISTS', 'INCRBY', 'MSET', 'MSETNX', 'SETBIT', 'SETEX', 'SETNX', 'BLPOP', 'QUIT', 'TIME', 'ECHO', 'ZCARD', 'LPUSH', 'LPUSHX', 'RPOP',
'EXPIRE', 'MIGRATE', 'GETBIT', 'GETRANGE', 'GETSET', 'MGET', 'HMGET', 'RESTORE', 'APPEND', 'HKEYS', 'HSET', 'HSETNX', 'HSTRLEN', 'BRPOP', 'BLPOP',
'LINDEX', 'LINSERT', 'LLEN', 'LRANGE', 'LREM', 'LSET', 'RPOP', 'LTRIM', 'ZCARD', 'ZCOUNT', 'ZINCRBY', 'ZRANGE', 'PUBLISH', 'PUBSUB', 'EVAL',
'INFO', 'SAVE'
];
/**
* RedisClient constructor.
* @param IP $IP
* @param Logger $logger
*/
public function __construct(IP $IP, Logger $logger)
{
$this->redis = new \Redis();
$this->IP = $IP;
$this->logger = $logger;
}
/**
* @param Address $address
* @param int $db
* @return \Redis|JsonResponse
*/
public function checkConn(Address $address, $db = 0)
{
try {
if (!$this->redis->connect($this->IP->resetIp($address->getIpAddress()), $address->getPort(), 5)) {
// if (!$this->redis->connect('10.141.4.80', $address->getPort(), 5)) {
return new JsonResponse([
'success' => false,
'message' => '连接失败',
'errorCode' => 'REDIS_AUTH_00001'
], 400, ['Access-Control-Allow-Origin' => '*']);
}
} catch (\RedisException $e) {
return new JsonResponse([
'success' => false,
'message' => $e->getMessage(),
'errorCode' => 'REDIS_AUTH_00001'
], 400, ['Access-Control-Allow-Origin' => '*']);
}
if ($address->getAuth()) {
try {
$this->redis->auth($address->getPassword());
} catch (\RedisException $e) {
return new JsonResponse([
'success' => false,
'message' => $e->getMessage(),
'errorCode' => 'REDIS_AUTH_00001'
], 400, ['Access-Control-Allow-Origin' => '*']);
}
}
try {
$this->redis->select($db);
} catch (\RedisException $e) {
return new JsonResponse([
'success' => false,
'message' => $e->getMessage(),
'errorCode' => 'REDIS_AUTH_00001'
], 400, ['Access-Control-Allow-Origin' => '*']);
}
return $this->redis;
}
/**
* @param $filter
* @return bool
*/
public function inFilter($filter)
{
return in_array(strtoupper(trim($filter)), $this->filter);
}
/**
* @param $key
* @param array $args
* @return array
*/
public function __call($key, array $args)
{
$args = $args[0];
unset($args[0]);
$this->logger->info("__call function.", ['key' => $key, 'args' => $args]);
$response = [];
try {
switch (count($args)) {
case 1:
$response = $this->redis->$key($args[1]);
break;
case 2:
$response = $this->redis->$key($args[1], $args[2]);
break;
case 3:
$response = $this->redis->$key($args[1], $args[2], $args[3]);
break;
case 4:
$response = $this->redis->$key($args[1], $args[2], $args[3], $args[4]);
break;
}
} catch (\RedisException $e) {
return new JsonResponse([
'success' => false,
'message' => $e->getMessage(),
'errorCode' => 'REDIS_AUTH_00001'
], 400, ['Access-Control-Allow-Origin' => '*']);
}
$return = [];
if (is_array($response)) {
foreach ($response as $item) {
$return[] = $item;
}
} else if (is_string($response)) {
$return[] = utf8_decode($response);
}
$this->redis->close();
return $return;
}
}
把这个类加入到服务中
# app/config/services.yml
services:
app.utils.IP:
class: AppBundle\Utils\IP
app.utils.redisClient:
class: AppBundle\Utils\RedisClient
arguments: ["@app.utils.ip", "@monolog.logger"] # 这里需要注入两个服务 一个是自己写的一个 一个是系统自带的logger服务
# calls: 这个以后再演示
# - [infoAction, [@app.utils.IP]] # 实例划后自动调用的方法
# tags: # 这个以后再说
然后就可以愉快的使用自己定义服务啦!
$redisClient = $this->get('app.utils.redisClient');
$redis = $redisClient->checkConn($addressInfo);
if ($redis instanceof JsonResponse) {
return $redis;
}
很赞哦! (2)
上一篇:Linux 开放端口服务
下一篇:一支钢笔,从头开始
文章评论
点击排行
本栏推荐
标签
站点信息
- 微信公众号