警告我們決定停止維護此軟體包。
考慮遷移到 spatie/laravel-data 或 cuyz/valinor。
請隨意分叉我們的程式碼並根據您的需求進行調整。
您可以透過 Composer 安裝該軟體包:
作曲家需要空間/資料傳輸對象
注意:此軟體包的 v3 僅支援php:^8.0
。如果您正在尋找舊版本,請查看 v2。
我們投入了大量資源來創建一流的開源套件。您可以透過購買我們的一款付費產品來支持我們。
我們非常感謝您從家鄉寄給我們一張明信片,並註明您正在使用我們的哪種套餐。您可以在我們的聯絡頁面上找到我們的地址。我們在虛擬明信片牆上發布所有收到的明信片。
該套件的目標是盡可能輕鬆地從(序列化)資料數組建構物件。 DTO 如下圖所示:
使用 SpatieDataTransferObjectAttributesMapFrom;使用 SpatieDataTransferObjectDataTransferObject;類別 MyDTO 擴充 DataTransferObject {公共OtherDTO $otherDTO; 公共OtherDTOCollection$集合; #[CastWith(ComplexObjectCaster::class)]public ComplexObject $complexObject; 公共 ComplexObjectWithCast $complexObjectWithCast; #[NumberBetween(1, 100)]public int $a; #[MapFrom('address.city')]public string $city; }
您可以像這樣建構這個 DTO:
$dto = 新的 MyDTO( 答:5, 收藏: [ ['id' => 1], ['id' => 2], ['id' => 3], ], 複雜物件:['名稱'=>'測試', ], ComplexObjectWithCast: ['名稱' => '測試', ], otherDTO: ['id' => 5], );
讓我們一一討論所有的可能性。
可以使用命名參數來建立 DTO。也可以仍然使用舊的陣列表示法。此範例與上面的範例等效。
$dto = new MyDTO(['a' => 5,'collection' => [ ['id' => 1], ['id' => 2], ['id' => 3], ],'complexObject' => ['名稱' => '測試', ],'complexObjectWithCast' => ['名稱' => '測試', ],'otherDTO' => ['id' => 5], ]);
如果 DTO 具有屬於另一個 DTO 或 DTO 集合的屬性,則該套件將自動將資料數組轉換為這些 DTO:
$dto = 新的 MyDTO( collection: [ // 這將成為 OtherDTOCollection['id' => 1] 類別的對象, ['id' => 2], // 每個項目都是 OtherDTO['id' => 3], ], otherDTO: ['id' => 5], // 該資料將會被轉換為 OtherDTO);
您可以建立自己的caster類,它將接受給定的任何輸入,並將該輸入轉換為所需的結果。
看一下ComplexObject
:
複雜物件類別 {公有字串$名稱; }
及其施法者ComplexObjectCaster
:
使用 SpatieDataTransferObjectCaster;類別 ComplexObjectCaster 實作 Caster {/** * @param array|mixed $value * * @return mix */public function 客群(mixed $value): ComplexObject{return new ComplexObject( 名稱:$值['名稱'] ); } }
您也可以在目標類別本身上定義該施法器,而不是指定每個屬性應使用哪個施法器:
MyDTO 類別擴展了 DataTransferObject {公共 ComplexObjectWithCast $complexObjectWithCast; }
#[CastWith(ComplexObjectWithCastCaster::class)]類別 ComplexObjectWithCast {公有字串$名稱; }
可以在 DTO 類別本身上定義預設腳輪。每當在 DTO 類別中遇到給定類型的屬性時,就會使用這些caster。
#[ DefaultCast(DateTimeImmutable::class, DateTimeImmutableCaster::class), DefaultCast(MyEnum::class, EnumCaster::class), ] 抽象類別 BaseDataTransferObject 擴充 DataTransferObject {public MyEnum $status; // 將使用 EnumCasterpublic DateTimeImmutable $date; // 將使用 DateTimeImmutableCaster}
任何caster都可以傳遞自訂參數,內建的ArrayCaster
實作是如何使用它的一個很好的例子。
將輸入傳遞給施法者時使用命名參數將有助於使您的程式碼更加清晰,但這不是必需的。
例如:
/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]公共陣列 $collectionWithNamedArguments; /** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, Foo::class)]公共陣列 $collectionWithoutNamedArguments;
請注意,傳遞給強制轉換建構函數的第一個參數始終是具有被強制轉換值類型的陣列。所有其他參數都將作為CastWith
屬性中的額外參數傳遞。
該包不提供任何特定的驗證功能,但它確實為您提供了一種構建自己的驗證屬性的方法。例如, NumberBetween
是使用者實現的驗證屬性:
MyDTO 類別擴展了 DataTransferObject { #[NumberBetween(1, 100)]public int $a; }
它的工作原理如下:
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]類 NumberBetween 實作 Validator {公用函數 __construct(私有 int $min,私有 int $max) { }public function validate(mixed $value): ValidationResult{if ($value < $this->min) {return ValidationResult::invalid("值應大於或等於 {$this->min}"); }if ($value > $this->max) {return ValidationResult::invalid("值應小於或等於 {$this->max}"); }回傳驗證結果::valid(); } }
您可以使用#[MapFrom]
屬性從具有不同名稱的來源屬性對應 DTO 屬性。
它與“點”表示法屬性名稱或索引一起使用。
PostDTO 類別擴展了 DataTransferObject { #[MapFrom('postTitle')]public string $title; #[MapFrom('user.name')]public string $author; }$dto = new PostDTO(['postTitle' => 'Hello world','user' => ['name' => 'John Doe'] ]);
UserDTO 類別擴充 DataTransferObject { #[MapFrom(0)]公有字串$firstName; #[MapFrom(1)]公有字串$lastName; }$dto = new UserDTO(['John', 'Doe']);
有時您還想在轉換為數組期間將它們映射。一個典型的用例是從駱駝案例到蛇案例的轉換。為此,您可以使用#[MapTo]
屬性。
UserDTO 類別擴充 DataTransferObject { #[地圖來源(0)] #[MapTo('first_name')]public string $firstName; #[地圖來源(1)] #[MapTo('last_name')]public string $lastName; }$dto = new UserDTO(['John', 'Doe']);$dto->toArray() // ['first_name' => 'John', 'last_name'=> 'Doe'];$dto- >only('first_name')->toArray() // ['first_name' => 'John'];
此套件的先前版本新增了FlexibleDataTransferObject
類,該類別允許您忽略DTO 上不存在的屬性。此行為已更改,預設情況下所有 DTO 現在都是靈活的,但您可以使用#[Strict]
屬性使其嚴格:
NonStrictDto 類別擴充了 DataTransferObject {公有字串$名稱; }// 這有效 new NonStrictDto( 名稱:'名稱', 未知:「未知」);
使用 SpatieDataTransferObjectAttributesStrict; #[Strict]類別 StrictDto 擴充 DataTransferObject {公有字串$名稱; }// 這會拋出 SpatieDataTransferObjectExceptionsUnknownProperties 異常new StrictDto( 名稱:'名稱', 未知:「未知」);
也提供了一些輔助函數,用於同時處理多個屬性。
$postData->all();$postData->only('標題', '正文') ->toArray(); $postData-> except('作者') ->toArray();
請注意, all()
將簡單地傳回所有屬性,而toArray()
也會將嵌套的 DTO 轉換為陣列。
您可以連結except()
和only()
方法:
$postData->除了('標題') ->除了('身體') ->toArray();
需要注意的是except()
和only()
是不可變的,它們不會改變原始資料傳輸物件。
該套件不會強制使用不可變對象,因為 PHP 不支援它們,但始終鼓勵您保持 DTO 不可變。為了幫助您,每個 DTO 上都有一個clone
方法,它接受要覆蓋的資料:
$clone = $original->clone(other: ['name' => 'a']);
請注意, $original
中的資料沒有更改。
此版本刪除了DataTransferObjectCollection
類別。相反,您可以使用簡單的腳輪和您自己的集合類別。
以下是將 DTO 集合轉換為 DTO 陣列的範例:
Bar 類別擴充了 DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(FooArrayCaster::class)]公共陣列 $collectionOfFoo; }類別 Foo 擴展了 DataTransferObject {公有字串$名稱; }
類別 FooArrayCaster 實作 Caster {public function cast(mixed $value): array{if (! is_array($value)) { throw new Exception("只能將陣列轉換成 Foo"); }return array_map(fn (array $data) => new Foo(...$data),$value); } }
如果你不想有多餘的類型提示,或是想要擴充的集合功能;您可以使用任何集合實作來建立自己的集合類別。在這個例子中,我們使用 Laravel 的:
Bar 類別擴充了 DataTransferObject { #[CastWith(FooCollectionCaster::class)]public CollectionOfFoo $collectionOfFoo; }類別 Foo 擴展了 DataTransferObject {公有字串$名稱; }
使用 IlluminateSupportCollection;class CollectionOfFoo 擴充 Collection {// 在這裡加入正確的回傳類型,以便靜態分析器知道這是哪種類型的陣列 public function offsetGet($key): Foo{returnparent::offsetGet($key); } }
FooCollectionCaster 類別實作 Caster {公用函數cast(混合$value): CollectionOfFoo{return new CollectionOfFoo(array_map(fn (array $data) => new Foo(...$data),$value)); } }
對於簡單的 DTO 陣列或實作 PHP 內建ArrayAccess
的對象,請考慮使用需要提供專案類型的ArrayCaster
:
Bar 類別擴充了 DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]公共陣列 $collectionOfFoo; }
作曲家測試
請參閱變更日誌以了解有關最近更改內容的更多資訊。
詳細資訊請參閱貢獻。
如果您發現有關安全的錯誤,請發送郵件至 [email protected],而不是使用問題追蹤器。
您可以自由使用這個軟體包,但如果它進入您的生產環境,我們非常感謝您從您的家鄉給我們寄一張明信片,註明您正在使用我們的哪個軟體包。
我們的地址是:Spatie, Kruikstraat 22, 2018 安特衛普, 比利時。
我們在公司網站上發布所有收到的明信片。
json2dto:一個用於將 JSON 物件轉換為 DTO 類別的 GUI(具有巢狀支援)。也提供了本地使用的 CLI 工具。
資料傳輸物件工廠:根據名稱和類型使用屬性的正確內容智慧產生 DTO 實例。
布倫特·羅斯
所有貢獻者
我們的Arr
類別包含從 Laravels Arr
助手複製的函數。
麻省理工學院許可證 (MIT)。請參閱許可證文件以獲取更多資訊。