剛開始接觸laravel,發現laravel默認的鑑權模塊密碼並未加鹽處理(密碼由password_hash方法建立)。因此本身琢磨着對密碼加鹽。像下面這樣校驗密碼(密碼在最初建立時,也以md5(salt . password .salt)的形式存儲)php
1 Auth::attempt(array('username'=>$user->username, 'password'=>$user->salt.Input::get('password').$user->salt))
但一直不成功,debug跟蹤源碼,能夠看到最後,EloquentUserProvider的validateCredentials方法進一步調用BcryptHasher的check方法,,再進一步調用vendor/ircmaxell/password-compat/lib/password.php:230 password_verify方法,而不是我起初所想的直接$user->password == md5('input_password')。所以我在這裏直接改寫了源碼,以此來實現密碼加鹽css
在任意響應中多四個空行,這個問題在4.2版本中遇到,而且在配置了auth過濾器的請求中才有html
這個問題在下載請求時會有問題,好比壓縮文件。在下載zip文件時,若是響應前步多幾個空行,會形成文件起始多幾個字節,形成這樣的錯誤mysql
warning [zip]: 8 extra bytes at beginning or within zipfile 。 由於代碼文件裏是windows 換行符 CRLF,因此四個空行是八個字符,因此響應頭部多了八個字節laravel
或者提示 該文件已損壞或者須要另外一個壓縮分卷git
有時須要服務端來清除cookie,以保證全部httponly屬性的cookie也能被清除。laravel已經提供API來生成清除cookie的http頭github
laravel 5.3中移出了controller路由,只保留了resources路由,這對開發規範的項目而言是好事,而對開發不規範的項目簡直是災難,開發不得不用get或者post路由爲每個控制器的方法註冊路由,這會形成路由文件routes.php(routes/web.php)文件巨大很差維護。我的比較喜歡按約定來,因此寫了個函數簡單實現controller路由(約定namespace/controller/method)格式,如Home/XxYyController@getMmGg 將映射到 url : home/xx-yy/mm-gg,而且是get請求web
1 /** 2 * 駝峯字符串轉蛇形字符串 3 * @param $str 4 * @param string $delimiter 5 * @return string 6 */ 7 function humpToSnake($str,$delimiter = '_'){ 8 if ( ! ctype_lower($str)) 9 { 10 $replace = '$1'.$delimiter.'$2'; 11 $str = strtolower(preg_replace('/([A-Za-z])([A-Z])/', $replace, $str)); 12 } 13 return $str; 14 } 15 16 17 /** 18 * 基於controller約定路由 19 * 例如: $namespace = 'H5' 20 * GET : XxYyController@getMmGg -> url : h5/xx-yy/mm-gg 21 * POST : XxYyController@postMmGg -> url : h5/xx-yy/mm-gg 22 * @param string $controller 控制器類名 23 * @param bool $namespace 相對於App\Http\Controllers的命名空間 24 */ 25 function routeController($controller,$namespace = false){ 26 if (preg_match('/([\w]+)Controller$/', $controller, $matches)) 27 { 28 $className = humpToSnake($matches[1],'-'); 29 $methods = get_class_methods('App\Http\Controllers\\'.($namespace ? $namespace.'\\' : '').$controller); 30 foreach($methods as $method){ 31 if(strpos($method,'get') === 0){ 32 // 註冊get路由 33 $methodName = humpToSnake(lcfirst(substr($method,3)),'-'); 34 Route::get($className.'/'.$methodName,$controller.'@'.$method); 35 } else if(strpos($method,'post') === 0){ 36 // 註冊post路由 37 $methodName = humpToSnake(lcfirst(substr($method,4)),'-'); 38 Route::post($className.'/'.$methodName,$controller.'@'.$method); 39 } 40 } 41 } 42 }
laravel使用的eloquent orm框架極其強大,大部分數據庫層面的操做都可以在不寫任何sql的狀況下實現查詢。因此在寫其他項目時,好比爬蟲,也想將此orm集成進來ajax
eloquent 是一個獨立的項目 https://github.com/illuminate/database,因此徹底能夠單獨拿出來用sql
經過composer在項目中安裝依賴
1 composer require illuminate/database:~4.2
將eloquent初始化的代碼獨立於一個php文件(start.php)中
1 <?php 2 /** 3 * Created by PhpStorm. 4 * User: lvyahui 5 * Date: 2016/3/17 6 * Time: 17:23 7 */ 8 require_once __DIR__ . '/vendor/autoload.php'; 9 require_once 'config.php'; 10 11 $localDBConf = config('db.local'); 12 13 $database = array( 14 'driver' => 'mysql', 15 'host' => $localDBConf['host'], 16 'port' => $localDBConf['port'], 17 'database' => $localDBConf['name'], 18 'username' => $localDBConf['user'], 19 'password' => $localDBConf['pass'], 20 'charset' => 'utf8', 21 'collation' => 'utf8_unicode_ci', 22 ); 23 24 //use Illuminate\Container\Container; 25 use Illuminate\Database\Capsule\Manager as Capsule; 26 27 $capsule = new Capsule(); 28 29 /*建立鏈接*/ 30 $capsule->addConnection($database); 31 /*設置全局訪問*/ 32 $capsule->setAsGlobal(); 33 /*啓動Eloquent*/ 34 $capsule->bootEloquent();
定義數據庫模型 BaseModel.php
1 <?php 2 use Illuminate\Database\Eloquent\Model as Eloquent; 3 /** 4 * Created by PhpStorm. 5 * User: samlv 6 * Date: 2016/3/17 7 * Time: 17:30 8 */ 9 class BaseModel extends Eloquent 10 { 11 protected $guarded = array('id'); 12 public $timestamps = false; 13 }
ApkClass.php
1 <?php 2 require_once ('BaseModel.php'); 3 /** 4 * Created by PhpStorm. 5 * User: lvyahui 6 * Date: 2016/3/31 7 * Time: 16:35 8 */ 9 class ApkClass extends BaseModel 10 { 11 protected $table = 'apk_class'; 12 }
在須要進行數據庫操做中引入初始化文件和模型文件便可以使用
1 <?php 2 /** 3 * Created by PhpStorm. 4 * User: lvyahui 5 * Date: 2016/3/31 6 * Time: 17:00 7 * 掃描tmp/zip目錄,解壓左右的zip包,讓後進行處理。 8 */ 9 require_once ('start.php'); 10 require_once ('models/ApkClass.php'); 11 12 foreach($usedApkClasss as $map_id=>$num){ 13 ApkClass::where('map_id',$map_id)->update(array('num' => $num)); 14 }
laravel 另外一個強大之處是其模板引擎,開發中經常使用的有兩種,視圖繼承和子視圖填充。這裏以子視圖填充爲例,按約定的方式簡化代碼的編寫
基礎控制器
1 <?php 2 3 use Illuminate\Support\Facades\View; 4 use Illuminate\Support\Facades\Redirect; 5 use Illuminate\Support\Facades\Input; 6 class BaseController extends Controller 7 { 8 9 protected $layout = 'layouts.site'; 10 11 protected $stdName = null; 12 13 protected $routeParams = false; 14 /** 15 * Setup the layout used by the controller. 16 * 17 * @return void 18 */ 19 protected function setupLayout() 20 { 21 if ( ! is_null($this->layout)) 22 { 23 $this->layout = View::make($this->layout); 24 } 25 } 26 27 public function __construct() 28 { 29 30 } 31 32 /** 33 * 獲取控制器名稱 34 * 例如: 35 * 類:admin/DataSourceController 36 * 將返回 37 * dataSource 38 * @return null|string 39 */ 40 public function getStdName() 41 { 42 if(!$this->stdName){ 43 $className = get_class($this); 44 if (preg_match('/([\w]+)Controller$/', $className, $matches)) 45 { 46 // $this->stdName = camel_case($matches[1]); 47 $this->stdName = lcfirst($matches[1]); 48 } 49 else 50 { 51 $this->stdName = $className; 52 } 53 } 54 return $this->stdName; 55 } 56 57 58 public function makeView($data = array(),$view = null){ 59 if(!$view){ 60 $routeParams = $this->getRouteParams(); 61 $controllerName = $routeParams['c']; 62 $methodName = $routeParams['m']; 63 if(preg_match('/^get(.*)$/',$methodName,$matches)){ 64 $methodName = StringUtils::humpToSnake($matches[1]); 65 } 66 $view = $controllerName.'.'.$methodName; 67 } 68 if(!is_array($data)){ 69 $data = array(); 70 } 71 if(Request::ajax()){ 72 return View::make($view,$data); 73 }else{ 74 $this->layout->nest('content',$view,$data); 75 return false; 76 } 77 } 78 79 /** 80 * 81 * @return array|bool 82 */ 83 public function getRouteParams(){ 84 if(!$this->routeParams){ 85 86 list($class,$method) = explode('@',Route::current()->getActionName()); 87 $class = str_replace("\\",".",substr($class,0,strrpos($class,'Controller'))); 88 // $names = explode(".",$class); 89 // foreach ($names as & $name) { 90 // $name = snake_case($name); 91 // } 92 $class = StringUtils::humpToSnake($class); 93 // $class = implode('.',$names); 94 95 $this->routeParams = array( 96 'c' => $class, 97 'm' => $method 98 ); 99 } 100 101 return $this->routeParams; 102 } 103 104 public function getRouteParam($key){ 105 $routePatams = $this->getRouteParams(); 106 return $routePatams[$key]; 107 } 108 109 }
控制器方法中只須要return makeView()方法便可,makeView方法會肯定視圖文件位置。
<?php class UserController extends BaseController { public function getList(){ return $this->makeView(array('users'=>array())); } }
主視圖(site.blade.php)寫法
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 @include('layouts.head') 5 <!-- 頁面級別css --> 6 @yield('page.level.css','') 7 </head> 8 <body> 9 @include('layouts.header') 10 <div class="container-fluid"> 11 {{$content}} 12 </div> 13 @include('layouts.footer') 14 <!-- 頁面級別js文件 --> 15 @yield('page.level.js','') 16 <!-- 頁面級別js代碼片斷 --> 17 @yield('page.level.script','') 18 </body> 19 </html>
上面幾份代碼實現這樣的約定是:UserController@getList方法渲染views/user/list.blade.php頁面,並將其填充到view/layouts/site.blade.php視圖中,也就是我認爲整個站點主視圖(佈局,layouts/site.blade.php)基本一致,全部方法產生的內容直接填充主視圖便可,那之後開發新的頁面或者接口,只須要按改約定開發便可