คำเตือน เราได้ตัดสินใจหยุดดูแลรักษาแพ็คเกจนี้
พิจารณาย้ายไปยัง spatie/laravel-data หรือ cuyz/valinor
อย่าลังเลที่จะแยกโค้ดของเราและปรับให้เข้ากับความต้องการของคุณ
คุณสามารถติดตั้งแพ็คเกจผ่านทางผู้แต่ง:
ผู้แต่งต้องการ spatie/data-transfer-object
หมายเหตุ : v3 ของแพ็คเกจนี้รองรับเฉพาะ php:^8.0
เท่านั้น หากคุณกำลังมองหาเวอร์ชันเก่า ลองดูเวอร์ชัน 2
เราลงทุนทรัพยากรจำนวนมากเพื่อสร้างแพ็คเกจโอเพ่นซอร์สที่ดีที่สุดในระดับเดียวกัน คุณสามารถสนับสนุนเราได้โดยการซื้อหนึ่งในผลิตภัณฑ์ที่ต้องชำระเงินของเรา
เราขอขอบคุณอย่างยิ่งที่คุณส่งโปสการ์ดจากบ้านเกิดของคุณถึงเรา โดยระบุว่าคุณใช้แพ็คเกจใดของเรา คุณจะพบที่อยู่ของเราในหน้าติดต่อของเรา เราเผยแพร่โปสการ์ดที่ได้รับทั้งหมดบนวอลล์โปสการ์ดเสมือนของเรา
เป้าหมายของแพ็คเกจนี้คือการสร้างออบเจ็กต์จากอาร์เรย์ของข้อมูล (แบบอนุกรม) ง่ายที่สุด DTO มีลักษณะดังนี้:
ใช้ SpatieDataTransferObjectAttributesMapFrom; ใช้ SpatieDataTransferObjectDataTransferObject; คลาส MyDTO ขยาย DataTransferObject {สาธารณะ OtherDTO $otherDTO; สาธารณะ OtherDTOCollection $collection; #[CastWith(ComplexObjectCaster::class)]สาธารณะ ComplexObject $complexObject; สาธารณะ ComplexObjectWithCast $ complexObjectWithCast; #[NumberBetween(1, 100)]public int $a; #[MapFrom('address.city')]สตริงสาธารณะ $city; -
คุณสามารถสร้าง DTO นี้ได้โดย:
$dto = MyDTO ใหม่( ก: 5, ของสะสม: [ ['id' => 1], ['id' => 2], ['id' => 3], - complexObject: ['ชื่อ' => 'ทดสอบ', - complexObjectWithCast: ['ชื่อ' => 'ทดสอบ', - อื่นๆDTO: ['id' => 5], -
เรามาหารือเกี่ยวกับความเป็นไปได้ทั้งหมดทีละรายการ
การสร้าง DTO สามารถทำได้โดยใช้อาร์กิวเมนต์ที่มีชื่อ คุณยังสามารถใช้สัญลักษณ์อาร์เรย์แบบเก่าได้ ตัวอย่างนี้เทียบเท่ากับตัวอย่างข้างต้น
$dto = ใหม่ MyDTO(['a' => 5,'collection' => [ ['id' => 1], ['id' => 2], ['id' => 3], ],'complexObject' => ['ชื่อ' => 'ทดสอบ', ],'complexObjectWithCast' => ['ชื่อ' => 'ทดสอบ', ],'otherDTO' => ['id' => 5], -
หาก DTO มีคุณสมบัติที่เป็น DTO อื่นหรือคอลเลกชัน DTO แพ็คเกจจะดูแลการส่งอาร์เรย์ของข้อมูลไปยัง DTO เหล่านั้นโดยอัตโนมัติ:
$dto = MyDTO ใหม่( คอลเลกชัน: [ // สิ่งนี้จะกลายเป็นวัตถุของคลาส OtherDTOCollection['id' => 1], ['id' => 2], // แต่ละรายการจะเป็นอินสแตนซ์ของ OtherDTO['id' => 3], - otherDTO: ['id' => 5], // ข้อมูลนี้จะถูกส่งไปยัง OtherDTO);
คุณสามารถสร้างคลาสแคสเตอร์ของคุณเองได้ ซึ่งจะนำอินพุตใดก็ตามที่ได้รับมา และจะแปลงอินพุตนั้นให้เป็นผลลัพธ์ที่ต้องการ
ดู ComplexObject
:
คลาส ComplexObject {สตริงสาธารณะ $name; -
และลูกล้อของมัน ComplexObjectCaster
:
ใช้ SpatieDataTransferObjectCaster; คลาส ComplexObjectCaster ใช้งาน Caster {/** * @param array|mixed $value * * @return mix */public function cast (mixed $value): ComplexObject{return new ComplexObject( ชื่อ: $value['ชื่อ'] - - -
แทนที่จะระบุว่าควรใช้ลูกล้อใดสำหรับแต่ละคุณสมบัติ คุณยังสามารถกำหนดลูกล้อนั้นในคลาสเป้าหมายได้:
คลาส MyDTO ขยาย DataTransferObject {สาธารณะ ComplexObjectWithCast $complexObjectWithCast; -
#[CastWith(ComplexObjectWithCastCaster::class)]คลาส ComplexObjectWithCast {สตริงสาธารณะ $name; -
เป็นไปได้ที่จะกำหนดลูกล้อเริ่มต้นในคลาส DTO เอง ลูกล้อเหล่านี้จะถูกนำมาใช้เมื่อใดก็ตามที่พบคุณสมบัติตามประเภทที่กำหนดภายในคลาส DTO
- DefaultCast(DateTimeImmutable::คลาส, DateTimeImmutableCaster::คลาส), DefaultCast(MyEnum::คลาส, EnumCaster::คลาส), ]คลาสนามธรรม BaseDataTransferObject ขยาย DataTransferObject {สถานะ $MyEnum สาธารณะ; // EnumCaster จะถูกใช้งาน DateTimeImmutable $date สาธารณะ; // DateTimeImmutableCaster จะถูกใช้}
แคสเตอร์ใดๆ สามารถส่งผ่านอาร์กิวเมนต์ที่กำหนดเองได้ การใช้งาน 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; -
มันทำงานเช่นนี้ภายใต้ประทุน:
#[แอตทริบิวต์(แอตทริบิวต์::TARGET_PROPERTY | คุณลักษณะ::IS_REPEATABLE)]คลาส NumberBetween ใช้ Validator { ฟังก์ชั่นสาธารณะ __ สร้าง (ส่วนตัว int $min, ส่วนตัว int $max) { }ตรวจสอบฟังก์ชันสาธารณะ (ผสม $value): ValidationResult{if ($value < $this->min) {return ValidationResult::invalid("ค่าควรมากกว่าหรือเท่ากับ {$this->min}"); }if ($value > $this->max) {return ValidationResult::invalid("ค่าควรน้อยกว่าหรือเท่ากับ {$this->max}"); } ส่งคืน ValidationResult::valid(); - -
คุณสามารถแมปคุณสมบัติ DTO จากคุณสมบัติแหล่งที่มาด้วยชื่ออื่นได้โดยใช้แอตทริบิวต์ #[MapFrom]
ใช้งานได้กับชื่อคุณสมบัติสัญลักษณ์ "จุด" หรือดัชนี
คลาส PostDTO ขยาย DataTransferObject - #[MapFrom('postTitle')]สตริงสาธารณะ $title; #[MapFrom('user.name')]สตริงสาธารณะ $author; }$dto = new PostDTO(['postTitle' => 'Hello world','user' => ['name' => 'John Doe'] -
คลาส UserDTO ขยาย DataTransferObject - #[MapFrom(0)]สตริงสาธารณะ $firstName; #[MapFrom(1)]สตริงสาธารณะ $lastName; }$dto = UserDTO ใหม่(['John', 'Doe']);
บางครั้งคุณอาจต้องการแมปพวกมันระหว่างการแปลงเป็น Array กรณีการใช้งานทั่วไปคือการเปลี่ยนจากกรณีอูฐไปเป็นกรณีงู เพื่อที่คุณสามารถใช้แอตทริบิวต์ #[MapTo]
คลาส UserDTO ขยาย DataTransferObject - #[แผนที่จาก(0)] #[MapTo('first_name')]สตริงสาธารณะ $firstName; #[แผนที่จาก(1)] #[MapTo('last_name')]สตริงสาธารณะ $lastName; }$dto = new UserDTO(['John', 'Doe']);$dto->toArray() // ['first_name' => 'John', 'last_name'=> 'Doe'];$dto- >เท่านั้น('first_name')->toArray() // ['first_name' => 'John'];
เวอร์ชันก่อนหน้าของแพ็คเกจนี้เพิ่มคลาส FlexibleDataTransferObject
ซึ่งอนุญาตให้คุณละเว้นคุณสมบัติที่ไม่มีอยู่ใน DTO ลักษณะการทำงานนี้มีการเปลี่ยนแปลง DTO ทั้งหมดมีความยืดหยุ่นตามค่าเริ่มต้น แต่คุณสามารถทำให้เข้มงวดได้โดยใช้แอตทริบิวต์ #[Strict]
:
คลาส NonStrictDto ขยาย DataTransferObject {สตริงสาธารณะ $name; }// ใช้งานได้ใหม่ NonStrictDto( ชื่อ: 'ชื่อ' ไม่ทราบ: 'ไม่ทราบ');
ใช้ SpatieDataTransferObjectAttributesStrict; #[Strict]คลาส StrictDto ขยาย DataTransferObject {สตริงสาธารณะ $name; }// สิ่งนี้จะพ่น SpatieDataTransferObjectExceptionsUnknownProperties ข้อยกเว้นใหม่ StrictDto( ชื่อ: 'ชื่อ' ไม่ทราบ: 'ไม่ทราบ');
นอกจากนี้ยังมีฟังก์ชันตัวช่วยบางอย่างสำหรับการทำงานกับคุณสมบัติหลายรายการพร้อมกัน
$postData->all();$postData->only('title', 'body') ->toArray(); $postData->ยกเว้น('ผู้เขียน') ->toArray();
โปรดทราบว่า all()
จะส่งกลับคุณสมบัติทั้งหมด ในขณะที่ toArray()
จะส่ง DTO ที่ซ้อนกันไปยังอาร์เรย์เช่นกัน
คุณสามารถเชื่อมโยงเมธอด except()
และ only()
:
$postData->ยกเว้น('ชื่อ') ->ยกเว้น('ร่างกาย') ->toArray();
สิ่งสำคัญคือต้องทราบว่า except()
และ only()
ที่ไม่เปลี่ยนรูป โดยจะไม่เปลี่ยนอ็อบเจ็กต์การถ่ายโอนข้อมูลดั้งเดิม
แพ็คเกจนี้ไม่บังคับวัตถุที่ไม่เปลี่ยนรูปเนื่องจาก PHP ไม่รองรับ แต่ขอแนะนำให้คุณรักษา DTO ของคุณให้ไม่เปลี่ยนรูปอยู่เสมอ เพื่อช่วยเหลือคุณ มีวิธี clone
ในทุก DTO ที่ยอมรับข้อมูลเพื่อแทนที่:
$clone = $Original->Clone(อื่นๆ: ['ชื่อ' => 'a']);
โปรดทราบว่าไม่มีการเปลี่ยนแปลงข้อมูลใน $original
เวอร์ชันนี้จะลบคลาส DataTransferObjectCollection
คุณสามารถใช้ล้อธรรมดาและคลาสคอลเลกชันของคุณเองแทนได้
ต่อไปนี้เป็นตัวอย่างของการส่งคอลเล็กชันของ DTO ไปยังอาร์เรย์ของ DTO:
คลาสบาร์ขยาย DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(FooArrayCaster::class)]อาร์เรย์สาธารณะ $collectionOfFoo; }คลาส Foo ขยาย DataTransferObject {สตริงสาธารณะ $name; -
คลาส FooArrayCaster ใช้ Caster { ฟังก์ชั่นสาธารณะหล่อ (ผสม $value): array{if (! is_array($value)) {throw new Exception("สามารถส่งอาร์เรย์ไปที่ Foo เท่านั้น"); }return array_map(fn (array $data) => new Foo(...$data),$value); - -
หากคุณไม่ต้องการคำใบ้การพิมพ์ที่ซ้ำซ้อน หรือต้องการฟังก์ชันการรวบรวมเพิ่มเติม คุณสามารถสร้างคลาสคอลเลกชั่นของคุณเองโดยใช้การใช้งานคอลเลกชั่นใดก็ได้ ในตัวอย่างนี้ เราใช้ของ Laravel:
คลาสบาร์ขยาย DataTransferObject - #[CastWith(FooCollectionCaster::class)]CollectionOfFoo $collectionOfFoo; }คลาส Foo ขยาย DataTransferObject {สตริงสาธารณะ $name; -
ใช้ IlluminateSupportCollection;class CollectionOfFoo ขยายคอลเลกชัน {// เพิ่มประเภทการส่งคืนที่ถูกต้องที่นี่เพื่อให้เครื่องวิเคราะห์คงที่ทราบว่าอาร์เรย์ประเภทใดที่เป็นฟังก์ชันสาธารณะ offsetGet($key): Foo{return parent::offsetGet($key); - -
คลาส FooCollectionCaster ใช้ Caster { ฟังก์ชั่นสาธารณะ (ผสม $value): CollectionOfFoo{return new CollectionOfFoo(array_map(fn (array $data) => new Foo(...$data),$value)); - -
สำหรับอาร์เรย์แบบง่ายของ DTO หรือออบเจ็กต์ที่ใช้ ArrayAccess
ในตัวของ PHP ให้พิจารณาใช้ ArrayCaster
ซึ่งกำหนดให้ต้องระบุประเภทรายการ:
คลาสบาร์ขยาย DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]อาร์เรย์สาธารณะ $collectionOfFoo; -
การทดสอบผู้แต่ง
โปรดดู CHANGELOG สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่เปลี่ยนแปลงเมื่อเร็วๆ นี้
โปรดดูการมีส่วนร่วมเพื่อดูรายละเอียด
หากคุณพบข้อบกพร่องเกี่ยวกับการรักษาความปลอดภัย โปรดส่งอีเมลมาที่ [email protected] แทนการใช้ตัวติดตามปัญหา
คุณสามารถใช้แพ็คเกจนี้ได้อย่างอิสระ แต่หากมันเหมาะกับสภาพแวดล้อมการใช้งานจริงของคุณ เราขอขอบคุณอย่างยิ่งที่คุณส่งโปสการ์ดจากบ้านเกิดของคุณมาให้เรา โดยระบุว่าคุณกำลังใช้แพ็คเกจใดของเรา
ที่อยู่ของเราคือ: Spatie, Kruikstraat 22, 2018 แอนต์เวิร์ป, เบลเยียม
เราเผยแพร่ไปรษณียบัตรที่ได้รับทั้งหมดบนเว็บไซต์ของบริษัทของเรา
json2dto: GUI สำหรับแปลงวัตถุ JSON เป็นคลาส DTO (พร้อมการรองรับการซ้อน) ยังมีเครื่องมือ CLI สำหรับการใช้งานในท้องถิ่น
Data Transfer Object Factory: สร้างอินสแตนซ์ DTO อย่างชาญฉลาดโดยใช้เนื้อหาที่ถูกต้องสำหรับคุณสมบัติของคุณตามชื่อและประเภท
เบรนต์ รูส
ผู้ร่วมให้ข้อมูลทั้งหมด
คลาส Arr
ของเรามีฟังก์ชันที่คัดลอกมาจากตัวช่วย Laravels Arr
ใบอนุญาตเอ็มไอที (MIT) โปรดดูไฟล์ใบอนุญาตสำหรับข้อมูลเพิ่มเติม