Laravel 11 中的 PHP 泛型
如果您是Laravel 的Web 應用程式建構者,並且碰巧使用PHPStan 進行靜態程式碼分析,那麼當您升級到Laravel 11.x.
使用PHPStan 全新安裝 Laravel 時,第一次執行 ./vendor/bin/phpstan 時會拋出以下錯誤:
------ ----------------------------------------------------------------------------------- Line app\Models\User.php ------ ----------------------------------------------------------------------------------- 13 Class App\Models\User uses generic trait Illuminate\Database\Eloquent\Factories\HasFactory but does not specify its types: TFactory ------ -----------------------------------------------------------------------------------
PHPDoc 和 @template 標籤,這是保留的泛型標籤之一。正如您可能已經猜到的,框架的許多部分都使用了泛型。
/** * @template TFactory of \Illuminate\Database\Eloquent\Factories\Factory */ trait HasFactory { ... }
parameters: ignoreErrors: - identifier: missingType.generics
什麼是泛型?
程式設計中的泛型是指允許您編寫可處理多種資料類型的程式碼的功能。您無需為每種資料類型編寫單獨的程式碼,而是可以編寫一段通用的程式碼,該程式碼可以在保持類型安全的同時對各種類型進行操作,這與使用混合或物件等通用類型不同。
採用
Laravel 10 中的 IlluminateDatabaseConcernsBuildsQueries::first 方法,它可以傳回 Model 的實例、通用物件、像 IlluminateDatabaseEloquentBuilder 一樣使用它的類別的實例或 null。
/** * Execute the query and get the first result. * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static|null */ public function first($columns = ['*']) { return $this->take(1)->get($columns)->first(); }
PHP 中不支援泛型作為一等公民,為了擁有它們,我們使用
PHPDocs 標籤 @template、@template-covariant、@template-contravariant、@extends、@implements 和@使用。
泛型類型的規則是使用型別參數定義的。 在PHPDocs中,我們使用@template標籤對它們進行註釋。類型參數名稱可以是任何名稱,只要不使用現有的類別名稱即可。您也可以使用 of 關鍵字限制可以使用哪些類型來取代帶有上限的類型參數。這稱為有界型參數。
<?php namespace Illuminate\Database\Eloquent; /** * @template TModel of \Illuminate\Database\Eloquent\Model * */ class Builder implements BuilderContract { }
通用函數
泛型函數與普通函數完全相同,但是它具有型別參數。這允許以更通用的方式使用通用方法。
以 IlluminateSupportValidatedInput::enum 方法為例:
- 它定義了一個型別參數 TEnum。
- $enumClass 參數是偽型別 class-string,並且綁定到相同型別參數 TEnum。
- 回傳型別也可以是 TEnum 或 null。
------ ----------------------------------------------------------------------------------- Line app\Models\User.php ------ ----------------------------------------------------------------------------------- 13 Class App\Models\User uses generic trait Illuminate\Database\Eloquent\Factories\HasFactory but does not specify its types: TFactory ------ -----------------------------------------------------------------------------------
如果您隨後呼叫 $request→validated()→enum('status', OrderStatus::class),PHPStan 將知道您正在取得 OrderStatus 物件或 null!
通用類別
泛型類別允許建立可以對任何資料類型進行操作的類,同時確保類型安全。它們允許使用特定類型的佔位符來定義類,稍後可以在類實例化時替換該佔位符。
Laravel 原始碼中的一個很好的例子是 IlluminateDatabaseEloquentBuilder 類別:
/** * @template TFactory of \Illuminate\Database\Eloquent\Factories\Factory */ trait HasFactory { ... }
類型參數 TModel 被定義並綁定到 IlluminateDatabaseEloquentModel 的任何子類別。相同的型別參數用作 make 方法的傳回類型。
另一個例子是,如果我們有一個訂單模型,它有一個本地範圍來根據訂單狀態過濾訂單。範圍方法應指定 TModel 類型
parameters: ignoreErrors: - identifier: missingType.generics
ℹ️ info:命名空間 IlluminateDatabaseEloquentRelations 中的所有 Eloquent 關係類別(例如 BelongsTo 和 HasOne)現在都是通用的。
通用介面
通用介面並沒有那麼不同。 IlluminateContractsSupportArrayable 是通用介面的範例
/** * Execute the query and get the first result. * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static|null */ public function first($columns = ['*']) { return $this->take(1)->get($columns)->first(); }
此介面定義了兩個型別參數:array-key類型的TKey(可以是int或string)和TValue。這兩個參數用於定義 toArray 函數的傳回類型。這是一個例子:
<?php namespace Illuminate\Database\Eloquent; /** * @template TModel of \Illuminate\Database\Eloquent\Model * */ class Builder implements BuilderContract { }
使用者類別實作 Arrayable 接口,並指定 Tkey 類型為 int,TValue 型為 string。
通用特徵
我們在本文開頭的錯誤中遇到了 IlluminateDatabaseEloquentFactoriesHasFactory 特徵。讓我們仔細看看:
/** * @template TEnum * * @param string $key * @param class-string<TEnum> $enumClass * @return TEnum|null */ public function enum($key, $enumClass) { if ($this->isNotFilled($key) || ! enum_exists($enumClass) || ! method_exists($enumClass, 'tryFrom')) { return null; } return $enumClass::tryFrom($this->input($key)); }
HasFactory 定義了一個型別參數 TFactory,它綁定到 IlluminateDatabaseEloquentFactoriesFactory 的子類別。那麼要如何修復這個錯誤呢?
使用 Trait 時必須指定 TFactory 類型。因此,HasFactory 特徵的 use 語句需要使用 PHPDocs @use:
進行註釋
<?php namespace Illuminate\Database\Eloquent; /** * @template TModel of \Illuminate\Database\Eloquent\Model */ class Builder implements BuilderContract { /** * @param array $attributes * @return TModel */ public function make(array $attributes = []) { return $this->newModelInstance($attributes); } }
保持通用性
擴充類別、實作介面或使用特徵時,可以保持子類別中的通用性。
透過在子類別上方定義相同的類型參數並將其傳遞給 @extends、@implements 和 @use 標籤來實現保留通用性。
我們將使用 IlluminateDatabaseConcernsBuildsQueries 通用特徵作為範例,
它定義了一個型別參數TValue:
------ ----------------------------------------------------------------------------------- Line app\Models\User.php ------ ----------------------------------------------------------------------------------- 13 Class App\Models\User uses generic trait Illuminate\Database\Eloquent\Factories\HasFactory but does not specify its types: TFactory ------ -----------------------------------------------------------------------------------
IlluminateDatabaseEloquentBuilder 類別使用此特徵,但透過向其傳遞 TModel 參數類型來保持其通用性。現在由客戶端程式碼來指定 TModel 的類型,從而在 BuildsQueries 特徵中指定 TValue。
/** * @template TFactory of \Illuminate\Database\Eloquent\Factories\Factory */ trait HasFactory { ... }
最後的想法
總之,雖然 PHP 並不像其他程式語言那樣原生支援泛型,但引入高階類型提示和工具(例如 PHPStan)允許開發人員在程式碼中實現類似泛型的功能。透過利用 PHPDocs、參數化類別和接口,您可以創建更靈活和類型安全的應用程序,從而提高程式碼的可重用性和可維護性。隨著 PHP 的不斷發展,社群對類型安全和靜態分析的日益關注可能會帶來更強大的泛型實現解決方案。接受這些實踐不僅可以提高您的編碼技能,還有助於開發經得起時間考驗的高品質軟體。
以上是Laravel 11 中的 PHP 泛型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

在PHP中使用預處理語句和PDO可以有效防範SQL注入攻擊。 1)使用PDO連接數據庫並設置錯誤模式。 2)通過prepare方法創建預處理語句,使用佔位符和execute方法傳遞數據。 3)處理查詢結果並確保代碼的安全性和性能。
