国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Laravel中的日志與上傳

2019-11-14 13:21:56
字體:
來源:轉載
供稿:網友

  php中的框架眾多,我自己就接觸了好幾個。大學那會啥也不懂啥也不會,拿了一個ThinkPHP學了。也許有好多人吐槽TP,但是個人感覺不能說哪個框架好,哪個框架不好,再不好的框架你能把源碼讀上一遍,框架的設計思想理解了也能學到好多東西。況且有好多東西自己還不理解,所以認真學習一個框架這還是可以學不少東西的。

  還是先說說Laravel吧,現在已經到5.2了。就我自己來說之前沒有接觸過laravel,但是學習過laravel之后感覺這個框架確實不錯,并且老外用的不亦樂乎。他的開發社區還可以,文檔比較齊全,但是官網文檔不咋地,從上面讀不出多少東西(自己感覺),好多東西還得閱讀源碼,對于我這種英語不好的人還更喜歡中文文檔(以后得改)。Laravel是使用Composer(https://getcomposer.org)來管理依賴,確實比較方便,但是因為鏡像被墻的原因在訪問或者更新的時候比較慢(幾乎失敗),這里有解決辦法:http://pkg.phpcomposer.com/#tip1。

  最近因為工作需要項目要重構(重構原因不用多說,大家懂得),需要遷移到新的框架上。Laravel是一個不錯的框架,強大的路由,便捷的配置,高可用的模塊依賴,確實為開發省了不少力氣。考慮到我們這個項目主要是接口部分,對性能有一定的要求(但是不是苛刻),并且路由不能改,要兼容老的邏輯,所以Laravel是首選,但是有一個問題就是我們是寫接口,那么要依賴的東西就少很多,比如view層幾乎用不到,還有就是測試模塊,上傳模塊(有圖床),本地化模塊文件系統等也用不到,所以使用Laravel還是比較浪費的,說白了他比較重。所以我們就考慮了基于laravel的一個框架Lumen,相比Laravel這個全棧框架而言Lumen精簡了不少,并且Lumen是面向Api的,所以最后就選擇Lumen了。

  laravel也不是全能的有優點也有缺點,比如他的依賴太多,可以看一下安裝好的laravel框架默認的依賴源包就有30M左右,確實有點大。直到今天在使用過程中發現Lumen也是有點力不從心,隨著業務邏輯越來越復雜,訪問速度各方面也下來了,我們有時候考慮 slim 等更輕量級的,其實吧新浪這邊不少人是鳥哥粉,不少人推崇yaf,yaf確實牛逼,實踐證明快的不止一點兩點,估計以后還得遷移到yaf。這段時間PHP7不是出了嗎,但是測試結果表明Bug不少,把接口遷移到7上應該有不少的性能提升,據說是提高100%,還沒敢嘗試,等穩定了再說吧!

  說了不少廢話,下面我就介紹一下Laravel中的日志與上傳,慢慢來,這篇文章先寫一部分,因為Laravel東西比較多,其他的我會慢慢寫出來。我就說說自己在使用過程中遇到的問題,遇到的坑,幫助大家學習。

一、日志

1、說明:

日志重要性不言而喻,我們這邊的日志是人工推薦,興趣愛好,推薦位的依賴。做推薦的同學比寫接口的還要多,日志出了問題,推薦就會不準確甚至無法推薦,可見日志的重要性。

Laravel框架初始化好了以后錯誤和異常處理已經默認配置好了,他的日志是基于一款很好用的日志管理工具Monolog,

  首先說一下Monolog,是php下比較全又容易擴展的記錄日志組件。其中Symfony 、 CakePHP等知名php框架都內置了Monolog,有興趣的可以看一下。每個Logger實例都有一個通道和日志處理器棧。每當你添加一條日志記錄,它會被發送到日志處理器棧。 你可以創建很多Logger每個Logger定義一個通道(db,請求,路由),每個Logger有很多日志處理器。這些通道會過濾日志。每個日志處理器都有一個Formatter(內置的日志顯示格式處理器)。你還可以設定日志級別。(官網解釋)

  日志配置:Laravel目前支持四種日志處理器,

1 Single(將日志記錄到單個文件中。該日志處理器對應,對應StreamHandler),2 3 Daily (以日期為單位將進行日志記錄對應RotatingFileHandler)4 5 Syslog(將日志記錄到Syslog中。對應SysLogHandler)6 7 Errorlog(將日志記錄到PHP的error_log中。對應ErrorLogHandler)

明白了日志的處理方式我們就可以設置自己需要的方式,在 config/app.php中的對應項設置(默認的):

1 'log' => 'single',

2、使用Log記錄日志

Laravel提供了Log方法記錄日志,Log實際上使用的 Illuminate/Log/Writer,應為在其中 Writer 的構造函數中注入Monolog/Logger。生成的日志文件存放在storage/logs目錄下。

如下:

1 Log::emergency($error); //緊急,如系統掛掉2 Log::alert($error);     //需要立即采取行動,如數據庫異常等3 Log::critical($error);  //嚴重問題,如異常4 Log::error($error);     //運行時錯誤,不需要立即處理但需要被記錄和監控5 Log::warning($error);   //警告但不是錯誤,比如使用了被廢棄的API6 Log::notice($error);    //普通但值得注意的事件7 Log::info($error);      //感興趣的事件,比如登錄、退出8 Log::debug($error);     //詳細的調試信息

3、按照自己的需求記錄日志

Laravel中如果按照原來的配置貌似不能按照自己的需求記錄日志,我就按照自己的需求寫了一個,供大家參考,當然你可以跳過他提供的日志處理方法Log,在容器中把 Monolog對象寫入容器,可以寫成單例的形式,這樣在加載的時候只實例化一次,然后按照monolog來配置自己想要的記錄日志的方法。

 1 class Save_log 2 { 3     //存放每個級別實例 4     PRivate static $obj_log = []; 5  6     //日志類型映射 7     private static $classify_arr = ['default', 'debug_log','error_log']; 8  9     /**10      * 單利初始化以及調取對象11      * @param $classify 日志的的頻道,對應不同的目錄12      * @param $max_num  日志記錄的最大數量13      */14     public static function get_log_instance($classify = 'default', $max_num = 0)15     {16         if(empty(self::$obj_log[$classify])) {17             self::$obj_log[$classify] = new Writer(new Logger($classify));18             self::$obj_log[$classify]->useDailyFiles(self::get_path($classify), $max_num);19         }20         return self::$obj_log[$classify];21     }22 23     /**24      * 映射對應的目錄25      * @param $classify 日志的不同的頻道26      */27     private static function get_path($classify)28     {29         $root_path = public_path();30         $path = $root_path . '/../../logs/'; //可以是自己的任意路徑31         $log_arr = self::$classify_arr;32         if(!empty($log_arr) && !empty($classify)) {33             if(in_array($classify, $log_arr)) {34                 return $path . $classify. '/' . $classify . '.log';35             }36         }37         return $path . 'default/default.log';38     }39 40     /**41      * 映射對應的目錄42      * @param $func 調用的方法43      * @param $arguments 參數,包括數據和日志等級44      */45     public static function __callStatic($func, $arguments)46     {47         $get_obj = self::get_log_instance($func);48         if(empty($get_obj)) {49             log::error('Save Log Error!');50         }51         if(empty($arguments) || !is_array($arguments) || !isset($arguments[0])) {52             $get_obj->info('No Data Save!');53         } else if(!isset($arguments[1])) {54             $get_obj->info($arguments[0]);55         } else {56             $get_obj->{$arguments[1]}($arguments[0]);57         }58     }59 }

使用的時候可以指定,如下:

1 Save_log::error_log($info, 'error');2 Save_log::debug_log($info);

日志內容如下:

二、上傳文件。

Laravel中的上傳文件是基于Flysystem提供的文件系統來實現上傳,刪除,移動。他支持多種驅動,還有一個值得看的云存儲,在SAE上需要用到。

文件系統配置位于Config/filesystems.php,我使用的試本地驅動。Laravel中的上傳目錄有兩個:public和Storage兩個,有人說這兩個一樣,其實是有區別的,應該說是各有好處,如果放在public中,服務器可以直接控制訪問,方便效率高,放在Storage中可以加上用戶控制比如權限等。

上傳需要的函數如下:

判斷是否進行了上傳,是否存在文件:

1 $request->hasFile('file')

判斷上傳是否出錯:

1 $file = $request->file('file');2 //判斷文件上傳過程中是否出錯3 if(!$file->isValid()) {4      exit('文件上傳出錯!');5 }

確定上傳:

1 $bytes = Storage::put(2       $savePath,3       file_get_contents($file->getRealPath())4 );

你也可以使用:

$path = $file -> move('storage/uploads');

生成縮略圖

Laravel木有提供函數生成縮略圖,但是我們可以借助強大的Composer來引入圖片處理庫 Integration/Image

在項目根目錄中的composer.json中的require中添加:"intervention/image": "dev-master",如下圖:

然后在config/app.php中providers數組中添加:

1 Intervention/Image/ImageServiceProvider::class

在aliases數組中添加別名:

1 'Image'     => Intervention/Image/Facades/Image::class,

這樣就可以使用了,在類文件中添加:

1 use Image;

下面是添加水印并且生成縮略圖:

$Image->text('@ u/'. $user_id, $news_width - 40 - $length * 10, $news_height - 24, function($font) {       $font->file('public/foos.ttf');       $font->size(14);       $font->color('#ffffff'); });

最后附上整個源碼,其中生成縮略圖部分可以抽象出來,因為有好幾個地方都需要用到,并且水印還有看圖片大小等等。

  1 /**  2  * 上傳文件  3  * @param  Object Request  4  * @return Json result  5  */  6 public function upload_file(Request $request)  7 {  8     $user_id = $request->get('user_id');  9     $width = $request->get('width'); 10     $height = $request->get('height'); 11     $upload_type = $request->get('upload_type'); 12     $watermark = $request->get('watermark'); 13  14     //參數檢查 15     if(empty($user_id)) { 16         return response()->json(['code' => 1001, 'msg' => '參數錯誤']); 17     } 18  19     //得到上傳文件名 20     if(!empty($_FILES)) { 21         $key_arr =  array_keys($_FILES); 22         $file_key = $key_arr[0]; 23     } 24      25     $file_key = !isset($file_key) || empty($file_key) ? 'fileselect' : $file_key; 26  27     if(!$request->hasFile($file_key)) { 28         return response()->json(['code' => 1002, 'msg' => '上傳文件為空']); 29     } 30  31     $upload_files = $request->file(); 32     if(empty($upload_files) || !is_array($upload_files)) { 33         return response()->json(['code' => 1003, 'msg' => '上傳失敗']); 34     } 35  36     //兼容單文件上傳 37     if(Utils::arrayLevel($upload_files) < 2) { 38         $files[$file_key][0] = $upload_files[$file_key]; 39     } else { 40         $files = $upload_files; 41     } 42  43     if($upload_type == 'userphoto' && count($files[$file_key]) > 1) { 44         return response()->json(['code' => 1004, 'msg' => '頭像只能上傳一張']); 45     } 46  47     if(count($files[$file_key]) > MAX_UPLOAD_FILE) { 48         return response()->json(['code' => 1005, 'msg' => '大于最大上傳數限制']); 49     } 50  51     //過濾大于MAX_FILE_SIZE的情況 52     foreach ($files[$file_key] as $key => $file) { 53         if($file-> getClientSize() > MAX_FILE_SIZE * 1024 * 1024) { 54             return response()->json(['code' => 1006, 'msg' => '文件大小不能超過']); 55         } 56     } 57  58     $file_info = []; 59     $length = strlen($user_id . ''); 60     //兼容批量上傳 61     foreach ($files[$file_key] as $key => $file) { 62         if(!$file->isValid()) { 63             return response()->json(['code' => 1007, 'msg' => '上傳出錯']); 64         } 65  66         if($upload_type == 'userpic') { 67             $file_dir = 'userpic'; 68         } else { 69             $type = $file->getMimeType(); 70             if(empty($type) && !is_array($type)) { 71                 return response()->json(['code' => 1008, 'msg' => '得到文件類型出錯']); 72             } 73  74             //映射文件類型 75             $type_arr = explode("/", $type); 76             switch($type_arr[0]){ 77                 case "image"      : $file_dir = "image"; break; 78                 case "video"      : $file_dir = "video"; break; 79                 case "audio"      : $file_dir = "voice"; break; 80                 case "text"       : $file_dir = "doc";   break; 81                 case "application": $file_dir = "doc";   break; 82                 default           : $file_dir = "other"; break; 83             } 84         } 85  86         //文件后綴 87         $postfix = $file->getClientOriginalExtension(); 88         $save_dir = UPLOAD_FILE_PATH; 89         $file_date = date('Ym'); 90         $file_name = $file_dir . '_' . $file_date . '_' . rand(111111, 999999) . $user_id; 91         $save_name = $file_name . '.' . $postfix; 92         $save_path = $file_dir . '/' . $file_date . '/' . $save_name; 93         Storage::put( 94             $save_path,  95             file_get_contents($file->getRealPath()) 96         ); 97         if(!Storage::exists($save_path)) { 98             return response()->json(['code' => 1009, 'msg' => '保存文件失敗']); 99         }100 101         //生成縮略圖102         if($file_dir == 'image' && (!empty($width) || !empty($height))) {103             $Image = Image::make($save_dir . $save_path);104             $img_width = $Image->width();105             $img_height = $Image->height();106 107             //如果有一個為空,則與另一個相等;108             if(empty($width)) {109                 //傳入的高度如果比實際高度大,就取實際高度110                 $height = $img_height < $height ? $img_height : $height;111                 $width = $height;112             } else if(empty($height)) {113                 $width = $img_width < $width ? $img_width : $width;114                 $height = $width;115             } else {116                 $height = $img_height < $height ? $img_height : $height;117                 $width = $img_width < $width ? $img_width : $width;118             }119 120             //拼接縮略圖路徑121             $Image->resize($width, $height);122             $save_name_s = $file_name . '_s.' . $postfix;123             $save_path_s = $save_dir . $file_dir . '/' . $file_date . '/' . $save_name_s;124             $file_path_s = $request->root() . '/' . $save_path_s;125 126             if($watermark != 1) {127                 //添加縮略圖水印128                 $news_width = $Image->width();129                 $news_height = $Image->height();130                 if($news_width > 100) {131                     $Image->text('@ u/'. $user_id, $news_width - 40 - $length * 10, $news_height - 24, function($font) {132                         $font->file('public/foos.ttf');133                         $font->size(14);134                         $font->color('#ffffff');135                     });136                 }137             }138 139             //保存縮略圖140             $Image->save($save_path_s, 100);141             $file_size_s = round($Image->filesize() / 1024 ,2) . 'K';142         }143 144         $file_path = $request->root() . '/' . $save_dir . $save_path;145         $file_size = round($file-> getClientSize() / 1024 ,2) . 'K';146         $file_info[] = compact(147             'save_name', 'file_size', 'file_path', 'save_name_s', 'file_size_s', 'file_path_s'148         );149     }150 151     if(empty($file_info)) {152         return response()->json(['code' => 1010, 'msg' => '異常出錯']);153     } else {154         return response()->json(['code' => 0, 'msg' => '', 'data' => $file_info]);155     }156 }

結束語:

以上是我學習中遇到的一部分問題,不對之處歡迎指正,這篇文章只是說了日志和上傳,以后會持續更新,包括路由,中間件,容器等等,還有好多需要說的。另外會同步更新到我的個人網站:www.zhaoyafei.cn,歡迎訪問

轉載注明出處

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 小金县| 高陵县| 习水县| 常熟市| 太康县| 建平县| 柘荣县| 天水市| 罗平县| 游戏| 红原县| 杨浦区| 门源| 霍山县| 云霄县| 洛扎县| 特克斯县| 伊金霍洛旗| 新昌县| 崇阳县| 宁安市| 柘荣县| 黑龙江省| 黎川县| 利辛县| 商南县| 固始县| 肥东县| 丰宁| 福泉市| 定安县| 卢氏县| 北辰区| 象州县| 邯郸县| 平遥县| 塔城市| 凌云县| 曲水县| 崇左市| 桦川县|