最近做了一款天气应用,看了前辈们的代码,学习到了不少的知识,特此记录下来。
1. 天气服务的接入
天气有多个服务提供商,如果将service层的代码写死的话,那么当天气提供商变化的时候,service层的代码完全不能用,做不到灵活的替换。为了避免这种问题,采用了动态绑定的方法。
目前是这样实现的:service->interface接口,interface接口可以在与具体的实现绑定在一起。
优化的逻辑方法:加一个中间件,然后在中间件中加策略,调用工厂模式来实现需求。具体代码如下所示:
class FaceplusMiddleware { /** * Handle an incoming request. * * @param $request * @param Closure $next * @return mixed * @throws AppExceptionsFaceplusParamException */ public function handle($request, Closure $next) { $driver = $request->header('driver', 'hub_acs'); app()->configure('faceplus'); $config = config('faceplus'); $strategy = array_get($config, $driver . '.strategy', []); $forwarding_driver = Util::tryMatchForwardingDriver($driver, $strategy); if ($forwarding_driver) { app()->bind(FaceContract::class, $forwarding_driver); } else { switch ($driver) { case 'hub_acs': app()->bind(FaceContract::class, HubAcs::class); break; case 'acs': app()->bind(FaceContract::class, Acs::class); break; case 'zhima': app()->bind(FaceContract::class, Zhima::class); break; default: list($code, $message) = ParamException::INVALID_HEAD_DRIVER; throw new ParamException($message, $code); break; } }return $next($request); } }
2. 图片剪裁
public function cutImage($image, $width, $height) { $imageSrc = env('WEATHER_IMAGE_HOST_CDN', 'https://img.vipplusclub.com/') . $image; // 拼接图片完整的url $type = $this->getTypeOfImage($imageSrc); // 获取图片文件的后缀 // 根据图片文件的后缀来调用获取图片的方法 if ($type == 'png') { $sourceImg =imagecreatefrompng($imageSrc); } if ($type == 'jpeg' || $type = 'jpg') { $sourceImg = imagecreatefromjpeg($imageSrc); } // 针对图片进行剪裁 $imageTemp = imagecreatetruecolor($width, $height); // 创建画板 $color = imagecolorallocatealpha($imageTemp, 255, 255, 255, 0); list($width_src, $height_src) = getimagesize($imageSrc); imagecopyresized($imageTemp, $sourceImg, 0,0, 0,0, $width, $height, $width_src, $height_src); $timeStamp = time(); $tmpFileName = '/tmp/weather_' . $timeStamp . '.jpg'; imagejpeg($imageTemp, $tmpFileName); imagedestroy($imageTemp); $result = $this->uploadYunService($tmpFileName); @unlink($imageTemp); return $result; }
3. 图片和文字打水印
阿里云文档地址:https://helpcdn.aliyun.com/document_detail/44957.html
操作代码:
protected function urlsafeB64encode($string) { $data = base64_encode($string); $data = str_replace(array('+','/','='), array('-','_',''), $data); return $data; }
protected function displayStruct($struct) { $format = []; foreach ($struct as $k => $v) { $format[] = $k . '_' .$v; } return '/watermark,' . implode(',', $format); }
protected function buildImageUrl($string, $x = 0, $y = 0, $g = 'se') { $base64Str = $this->urlsafeB64encode($string); $struct = [ 'g' => $g, 'image' => $base64Str, 'x' => $x, 'y' => $y, ]; return $this->displayStruct($struct); } protected function buildTextUrl($string, $size = 15, $x = 0, $y = 0, $color = '000000', $fontType = 'd3F5LXplbmhlaQ') { $base64Str = $this->urlsafeB64encode($string); $struct = [ 'type' => $fontType, 'size' => $size, 'text' => $base64Str, 'x' => $x, 'y' => $y, 'color' => $color, ]; return $this->displayStruct($struct); }
$config = config('weather'); $orig = env('IMAGE_HOST', 'http://vipplus-public-bucket.oss-cn-hangzhou.aliyuncs.com/') . array_get($config, 'menuCover') . array_get($config, 'menuCoverSuf'); $areaUrl = $this->buildTextUrl($areaName, 30, 560, 1040, '2D3A50', 'ZmFuZ3poZW5naGVpdGk'); $iconUrl = $this->buildImageUrl( array_get($currentWeather, 'wea_img_path'), 380, 160 ); //因为阿里云最多支持3组汉字 $path = $orig.$areaUrl.$iconUrl; $image1 = imagecreatefromjpeg($path); $ttf = __DIR__.'/ttf/jian.ttf'; $color = imagecolorallocatealpha($image1, 255, 255, 255, 0); imagettftext( $image1, 30, 0, 50, 1230, $color, $ttf, array_get($currentWeather, 'win') . ' ' . array_get($currentWeather, 'win_speed') );
4. 执行方法前先读缓存
protected function handleCache($cacheKey, $funcName, $cityId) { if ($this->needCache) { $cacheData = $this->redisService->get($cacheKey); if (!empty($cacheData)) { return $cacheData; } } $return = $this->{$funcName}($cityId); if ($this->needCache) { $this->redisService->put($cacheKey, $return, $this->getCacheExpireMinute()); } return $return; }