Laravel 檔案上傳和獲取請求引數

cangsongbayu發表於2020-01-07

Laravel 中訪問使用者資料的最常見工具是注入 Illuminate\Http\Request 物件

通過 Illuminate\Http\Request 可以訪問各種形式的請求資料 :POST 、GET 、URL 片段等

// 注入 Illuminate\Http\Request 物件
Route::post('form', function(Illuminate\Http\Request $request){
    // 這樣就注入成功了 ,然後就可以使用 $request 的各種成員來獲取請求資訊了
});

Laravel 的 Illuminate\Http\Request 繼承自 Symfony 框架的 Symfony\Component\HttpFoundation\Request

下面列出的成員可能存在於 Illuminate\Http\Request 中 ,也可能存在於 Symfony\Component\HttpFoundation\Request ,這裡沒做出區分

2.1 獲取請求引數的成員

成員 說明 示例
all() 獲取所有請求引數 $request->all()
except() 返回值與 all() 相同 ,但可以設定要排除的欄位 ,比如 _token() $request->except('_token')
only() 返回值與 all() 相同 ,但可以手動指定獲取哪些欄位 $request->only(['firstName', 'lastName'])
input() input() 與 only() 類似 ,但只能獲取單個欄位的值 $request->input('firstName')
query() 僅從查詢字串中獲取引數值 $request->query('queryName', 'default')

2.2 檢測相關的成員

成員 說明 示例
has() 檢測請求欄位是否存在 ,如果 key 存在並且為空 ,has() 會返回 false $request->has(['name', 'email'])
exists() 檢測請求欄位是否存在 ,如果 key 存在就算是空的 ,exists() 也返回 true $request->exists('firstName')
is(...$patterns) 如果當前 URI 與給定的正規表示式匹配返回 true -
routeIs(...$patterns) 如果當前路由名稱與給定的正規表示式匹配返回 true -
fullUrlIs(...$patterns) 如果當前的 URL 與給定正規表示式匹配返回 true -
ajax() 如果是 AJAX 請求返回 true -
pjax() 如果是 PJAX 請求返回 true -
secure() 如果是 HTTPS 請求返回 true -
isMethod($method) 如果是給定的請求型別返回 true $request->isMethod('POST')

2.3 上傳檔案相關的成員

成員 說明 示例
file() 獲取上傳檔案資訊 $request->file('profile_picture')
hasFile() 如果請求有上傳檔案 ,返回 true $request->hasFile('profile_picture')

2.4 請求描述資訊相關的成員

成員 說明 示例
method() 返回請求的型別 POST 、GET
ip() 返回客戶端 IP -
ips() 返回客戶端 IP ,陣列 -
userAgent() 返回 User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
fingerprint() 返回對當前路由 、域名 、URI 、IP 進行 sha1 計算後的雜湊值 f93ae561bed07f6e902ebab927e59489c9f70934

2.5 URL 相關的成員

成員 說明 示例
root() 返回應用程式的根 URL http://testl.lo
url() 獲取請求的 URL ,不包含查詢字串 http://testl.lo/recipse
fullUrl() 獲取請求的 URL ,包含查詢字串 http://testl.lo/recipse?a=b
fullUrlWithQuery(array $query) 根據完整的 URL 和傳入的查詢字串返回一個新的 URL $request->fullUrlWithQuery(['a' => 'b'])
path() 獲取請求的路徑資訊 -
segments() 返回所有的 URI 片段組成的陣列 ,不包含域名 $request->segments()
segment($index, $default = null) 返回指定的 URI 片段 ,路徑索引是基於 1 的 $request->segment(1)

2.6 操作請求資訊的成員

成員 說明 示例
merge(array $input) 將新的請求引數合併到當前請求引數中 -
replace(array $input) 替換當前請求引數( 會完全覆蓋 ) -

2.7 Session 相關的成員

成員 說明 示例
session() 返回 \Illuminate\Session\Store 例項 -
getSession() 返回 \Illuminate\Session\Store 例項 -

2.8 其他成員

成員 說明 示例
instance() 返回當前物件 -

Laravel 還為訪問陣列型別的輸入資料提供了 "." 語法

<form method="post" action="/post-route">
    {{ csrf_field() }}
    <input type="text" name="employees[0][firstName]" />
    <input type="text" name="employees[0][lastName]" />
    <input type="text" name="employees[1][firstName]" />
    <input type="text" name="employees[1][lastName]" />
</form>
Route::post('/post-route', function(Request $request){
    // 假如表單填寫為 張 、三 、李 、四
    $request->input('employees.0.firstName'); // '張'
    $request->input('employees.*.lastName'); // ['三', '四']
    $request->input('employees.1'); // ['firstName' => '張', 'lastName' => '三']
})

4.1 獲取上傳檔案

Laravel 使用 Illuminate\Http\Request 的 file() 方法來獲取使用者上傳的檔案 ,並返回 Symfony\Component\HttpFoundation\File\UploadedFile 的例項

$request->file('photo');
// 或者
$request->photo;

4.2 驗證檔案上傳

使用 Symfony\Component\HttpFoundation\File\UploadedFile 的 isValid() 方法驗證檔案是否上傳成功

if ($request->hasFile('file') && $request->file('file')->isValid()) {
    // isValid() 在檔案自身上呼叫 ,如果沒有上傳檔案就呼叫會產生報錯 , 因此先使用 hasFile() 檢測是否有上傳檔案
}

4.3 Symfony\Component\HttpFoundation\File\UploadedFile 成員

// 這裡列出一下繼承關係
Symfony\Component\HttpFoundation\File\UploadedFile extends Symfony\Component\HttpFoundation\File\File;

方法名中帶有 Client 的 ,表示相關資訊是從客戶端請求中提取出來的 ,因此值不一定可信 ,因為這些值都可以通過爬蟲來偽造

成員 說明 示例
getClientOriginalName() 返回上傳檔案的原始名稱 -
getClientOriginalExtension() 返回上傳檔案的字尾名 -
getClientMimeType() 返回上傳檔案的 MIME 型別 -
guessClientExtension() 返回上傳檔案的字尾名 -
getClientSize() 返回上傳檔案的位元組大小 -
getError() 返回上傳檔案的錯誤資訊 ,成功返回 UPLOAD_ERR_OK 常量 ,失敗返回 UPLOAD_ERR_XXX 系列的其他常量 -
isValid() 驗證檔案是否成功上傳 -
move($directory, $name = null) 將上傳移動到 $directory + $name( 如果有 ) -
getMaxFilesize() 返回 php.ini 中 upload_max_filesize 配置的值 -
getErrorMessage() 返回上傳檔案產生的錯誤資訊 -

說明一下 ,還有很多其他可用的方法( 繼承來的 ) 這裡只列出了 UploadedFile 自身的成員( 不包含繼承來的 )

4.4 錯誤常量和錯誤資訊

/**
 * Returns an informative upload error message.
 *
 * @return string The error message regarding the specified error code
 */
public function getErrorMessage()
{
    static $errors = array(
        UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
        UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
        UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
        UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
        UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
        UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
        UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.',
    );
    $errorCode = $this->error;
    $maxFilesize = $errorCode === UPLOAD_ERR_INI_SIZE ? self::getMaxFilesize() / 1024 : 0;
    $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.';
    return sprintf($message, $this->getClientOriginalName(), $maxFilesize);
}

4.5 Symfony\Component\HttpFoundation\File\File 成員

// SplFileInfo 是 PHP 的原生類
Symfony\Component\HttpFoundation\File\File extends \SplFileInfo;
成員 說明 示例
guessExtension() 根據檔案的 MIME 型別返回檔案字尾名 ,失敗返回 null -
getMimeType() 返回檔案的 MIME 型別 -

還可以用 request() 全域性函式和 Request facade 實現 ,這兩種方式都依賴於 Illuminate\Http\Request 物件

// 如果要使用 facade ,必須匯入完整的 facade 路徑
use Illuminate\Support\facades\Request;

// 然後就能用了 ,跟 Illuminate\Http\Request 都差不多
Request::input('title');

使用全域性助手函式就更方便了 ,直接用就好了

request()->input('title');
// 還有一個預設的規則 ,當傳遞一個引數時 request('title') 是 request()->input('title') 的快捷方式
request('title');
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章