两个小例子来说明symfony中如何自写义自己的services,真的非常简单。
官方文档是这么说的:
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; } }
下面一个简单的例子来说明:
打开 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位 }
// 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; }