Warnung: Wir haben beschlossen, die Wartung dieses Pakets einzustellen.
Erwägen Sie die Migration zu spatie/laravel-data oder cuyz/valinor.
Fühlen Sie sich frei, unseren Code zu forken und an Ihre Bedürfnisse anzupassen.
Sie können das Paket über Composer installieren:
Komponist benötigt Spatie/Data-Transfer-Objekt
Hinweis : Version 3 dieses Pakets unterstützt nur php:^8.0
. Wenn Sie nach der älteren Version suchen, schauen Sie sich Version 2 an.
Wir investieren viele Ressourcen in die Erstellung erstklassiger Open-Source-Pakete. Sie können uns unterstützen, indem Sie eines unserer kostenpflichtigen Produkte kaufen.
Wir freuen uns sehr, dass Sie uns eine Postkarte aus Ihrer Heimatstadt schicken und erwähnen, welches unserer Pakete Sie verwenden. Unsere Adresse finden Sie auf unserer Kontaktseite. Wir veröffentlichen alle erhaltenen Postkarten auf unserer virtuellen Postkartenwand.
Das Ziel dieses Pakets besteht darin, die Konstruktion von Objekten aus Arrays von (serialisierten) Daten so einfach wie möglich zu machen. So sieht ein DTO aus:
use SpatieDataTransferObjectAttributesMapFrom;use SpatieDataTransferObjectDataTransferObject;class MyDTO erweitert DataTransferObject {public OtherDTO $otherDTO; öffentliche OtherDTOCollection $collection; #[CastWith(ComplexObjectCaster::class)]public ComplexObject $complexObject; public ComplexObjectWithCast $complexObjectWithCast; #[NumberBetween(1, 100)]public int $a; #[MapFrom('address.city')]public string $city; }
Sie könnten dieses DTO folgendermaßen erstellen:
$dto = neues MyDTO( a: 5, Sammlung: [ ['id' => 1], ['id' => 2], ['id' => 3], ], complexObject: ['name' => 'test', ], complexObjectWithCast: ['name' => 'test', ], otherDTO: ['id' => 5], );
Lassen Sie uns alle Möglichkeiten einzeln besprechen.
Die Erstellung eines DTO kann mit benannten Argumenten erfolgen. Es ist auch möglich, weiterhin die alte Array-Notation zu verwenden. Dieses Beispiel entspricht dem obigen.
$dto = new MyDTO(['a' => 5,'collection' => [ ['id' => 1], ['id' => 2], ['id' => 3], ],'complexObject' => ['name' => 'test', ],'complexObjectWithCast' => ['name' => 'test', ],'otherDTO' => ['id' => 5], ]);
Wenn ein DTO über eine Eigenschaft verfügt, die ein anderes DTO oder eine DTO-Sammlung ist, sorgt das Paket dafür, dass Datenarrays automatisch in diese DTOs umgewandelt werden:
$dto = neues MyDTO( Sammlung: [ // Dies wird ein Objekt der Klasse OtherDTOCollection['id' => 1], ['id' => 2], // Jedes Element ist eine Instanz von OtherDTO['id' => 3], ], otherDTO: ['id' => 5], // Diese Daten werden in OtherDTO umgewandelt);
Sie können Ihre eigenen Caster-Klassen erstellen, die alle ihnen gegebenen Eingaben entgegennehmen und diese Eingaben in das gewünschte Ergebnis umwandeln.
Schauen Sie sich das ComplexObject
an:
Klasse ComplexObject {öffentliche Zeichenfolge $name; }
Und sein Caster ComplexObjectCaster
:
Verwenden Sie SpatieDataTransferObjectCaster; die Klasse ComplexObjectCaster implementiert Caster {/** * @param array|mixed $value * * @return Mixed */public function cast(mixed $value): ComplexObject{return new ComplexObject( Name: $value['name'] ); } }
Anstatt anzugeben, welcher Caster für jede Eigenschaft verwendet werden soll, können Sie diesen Caster auch für die Zielklasse selbst definieren:
Die Klasse MyDTO erweitert DataTransferObject {public ComplexObjectWithCast $complexObjectWithCast; }
#[CastWith(ComplexObjectWithCastCaster::class)]class ComplexObjectWithCast {öffentliche Zeichenfolge $name; }
Es ist möglich, Standardcaster für eine DTO-Klasse selbst zu definieren. Diese Caster werden immer dann verwendet, wenn eine Eigenschaft mit einem bestimmten Typ innerhalb der DTO-Klasse gefunden wird.
#[ DefaultCast(DateTimeImmutable::class, DateTimeImmutableCaster::class), DefaultCast(MyEnum::class, EnumCaster::class), ]Abstrakte Klasse BaseDataTransferObject erweitert DataTransferObject {public MyEnum $status; // EnumCaster wird verwendetpublic DateTimeImmutable $date; // DateTimeImmutableCaster wird verwendet}
Jedem Caster können benutzerdefinierte Argumente übergeben werden. Die integrierte ArrayCaster
-Implementierung ist ein gutes Beispiel dafür, wie dies verwendet werden kann.
Die Verwendung benannter Argumente bei der Übergabe von Eingaben an Ihren Caster trägt dazu bei, Ihren Code klarer zu gestalten, sie sind jedoch nicht erforderlich.
Zum Beispiel:
/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]public array $collectionWithNamedArguments; /** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, Foo::class)]public array $collectionWithoutNamedArguments;
Beachten Sie, dass das erste Argument, das an den Caster-Konstruktor übergeben wird, immer das Array mit den Typen des umzuwandelnden Werts ist. Alle anderen Argumente werden als zusätzliche Argumente im CastWith
-Attribut übergeben.
Dieses Paket bietet keine spezifische Validierungsfunktionalität, bietet Ihnen jedoch die Möglichkeit, Ihre eigenen Validierungsattribute zu erstellen. NumberBetween
ist beispielsweise ein vom Benutzer implementiertes Validierungsattribut:
Die Klasse MyDTO erweitert DataTransferObject { #[NumberBetween(1, 100)]public int $a; }
Unter der Haube funktioniert es so:
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]class NumberBetween implementiert Validator {öffentliche Funktion __construct(private int $min,private int $max) { }public functionvalidate(mixed $value): ValidationResult{if ($value < $this->min) {return ValidationResult::invalid("Wert sollte größer oder gleich {$this->min} sein"); }if ($value > $this->max) {return ValidationResult::invalid("Wert sollte kleiner oder gleich {$this->max} sein"); }return ValidationResult::valid(); } }
Mit dem Attribut #[MapFrom]
können Sie eine DTO-Eigenschaft einer Quelleigenschaft mit einem anderen Namen zuordnen.
Es funktioniert mit einem Eigenschaftsnamen oder einem Index in „Punkt“-Notation.
Die Klasse PostDTO erweitert DataTransferObject { #[MapFrom('postTitle')]public string $title; #[MapFrom('user.name')]public string $author; }$dto = new PostDTO(['postTitle' => 'Hello world','user' => ['name' => 'John Doe'] ]);
Die Klasse UserDTO erweitert DataTransferObject { #[MapFrom(0)]public string $firstName; #[MapFrom(1)]public string $lastName; }$dto = new UserDTO(['John', 'Doe']);
Manchmal möchten Sie sie auch während der Transformation in ein Array zuordnen. Ein typischer Anwendungsfall wäre die Umwandlung von einem Kamelgehäuse in ein Schlangengehäuse. Dazu können Sie das Attribut #[MapTo]
verwenden.
Die Klasse UserDTO erweitert DataTransferObject { #[MapFrom(0)] #[MapTo('first_name')]public string $firstName; #[MapFrom(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'];
In der vorherigen Version dieses Pakets wurde die Klasse FlexibleDataTransferObject
hinzugefügt, mit der Sie Eigenschaften ignorieren konnten, die im DTO nicht vorhanden waren. Dieses Verhalten wurde geändert. Alle DTOs sind jetzt standardmäßig flexibel. Sie können sie jedoch streng festlegen, indem Sie das Attribut #[Strict]
verwenden:
Die Klasse NonStrictDto erweitert DataTransferObject {öffentliche Zeichenfolge $name; }// Das funktioniertnew NonStrictDto( Name: 'Name', unbekannt: 'unbekannt');
use SpatieDataTransferObjectAttributesStrict; #[Strict]class StrictDto erweitert DataTransferObject {öffentliche Zeichenfolge $name; }// Dies löst eine SpatieDataTransferObjectExceptionsUnknownProperties-Ausnahme aus.new StrictDto( Name: 'Name', unbekannt: 'unbekannt');
Es stehen auch einige Hilfsfunktionen zur Verfügung, mit denen Sie mit mehreren Eigenschaften gleichzeitig arbeiten können.
$postData->all();$postData->only('title', 'body') ->toArray(); $postData->exclusiv('author') ->toArray();
Beachten Sie, dass all()
einfach alle Eigenschaften zurückgibt, während toArray()
auch verschachtelte DTOs in Arrays umwandelt.
Sie können die Methoden except()
und only()
verketten:
$postData->exclusive('title') ->außer('Körper') ->toArray();
Es ist wichtig zu beachten, dass except()
und only()
unveränderlich sind und das ursprüngliche Datenübertragungsobjekt nicht ändern.
Dieses Paket erzwingt keine unveränderlichen Objekte, da PHP diese nicht unterstützt. Wir empfehlen Ihnen jedoch immer, Ihre DTOs unveränderlich zu halten. Um Ihnen zu helfen, gibt es in jedem DTO eine clone
, die Daten zum Überschreiben akzeptiert:
$clone = $original->clone(other: ['name' => 'a']);
Beachten Sie, dass keine Daten in $original
geändert werden.
Diese Version entfernt die DataTransferObjectCollection
-Klasse. Stattdessen können Sie einfache Caster und Ihre eigenen Sammlungsklassen verwenden.
Hier ist ein Beispiel für die Umwandlung einer Sammlung von DTOs in ein Array von DTOs:
Die Klasse Bar erweitert DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(FooArrayCaster::class)]public array $collectionOfFoo; }class Foo erweitert DataTransferObject {öffentliche Zeichenfolge $name; }
Die Klasse FooArrayCaster implementiert Caster {public function cast(mixed $value): array{if (! is_array($value)) {throw new Exception("Kann Arrays nur in Foo umwandeln"); }return array_map(fn (array $data) => new Foo(...$data),$value); } }
Wenn Sie den redundanten Typehint nicht möchten oder eine erweiterte Sammlungsfunktionalität wünschen; Sie könnten Ihre eigenen Sammlungsklassen mit jeder Sammlungsimplementierung erstellen. In diesem Beispiel verwenden wir Laravel's:
Die Klasse Bar erweitert DataTransferObject { #[CastWith(FooCollectionCaster::class)]public CollectionOfFoo $collectionOfFoo; }class Foo erweitert DataTransferObject {öffentliche Zeichenfolge $name; }
use IlluminateSupportCollection;class CollectionOfFoo erweitert Collection {// Fügen Sie hier den richtigen Rückgabetyp hinzu, damit statische Analysatoren wissen, um welchen Array-Typ es sich handelt. öffentliche Funktion offsetGet($key): Foo{return parent::offsetGet($key); } }
Die Klasse FooCollectionCaster implementiert Caster {public function cast(mixed $value): CollectionOfFoo{return new CollectionOfFoo(array_map(fn (array $data) => new Foo(...$data),$value)); } }
Für ein einfaches Array von DTOs oder ein Objekt, das PHPs integrierten ArrayAccess
implementiert, sollten Sie die Verwendung des ArrayCaster
in Betracht ziehen, der die Bereitstellung eines Elementtyps erfordert:
Die Klasse Bar erweitert DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]public array $collectionOfFoo; }
Komponistentest
Weitere Informationen zu den letzten Änderungen finden Sie im CHANGELOG.
Weitere Informationen finden Sie unter BEITRAGEN.
Wenn Sie einen Sicherheitsfehler gefunden haben, senden Sie bitte eine E-Mail an [email protected], anstatt den Issue-Tracker zu verwenden.
Es steht Ihnen frei, dieses Paket zu verwenden, aber wenn es in Ihre Produktionsumgebung gelangt, würden wir uns sehr freuen, wenn Sie uns eine Postkarte aus Ihrer Heimatstadt schicken und erwähnen, welches unserer Pakete Sie verwenden.
Unsere Adresse lautet: Spatie, Kruikstraat 22, 2018 Antwerpen, Belgien.
Wir veröffentlichen alle erhaltenen Postkarten auf unserer Firmenwebsite.
json2dto: eine GUI zum Konvertieren von JSON-Objekten in DTO-Klassen (mit Verschachtelungsunterstützung). Bietet außerdem ein CLI-Tool für die lokale Verwendung.
Data Transfer Object Factory: Generiert auf intelligente Weise eine DTO-Instanz mit dem richtigen Inhalt für Ihre Eigenschaften basierend auf ihrem Namen und Typ.
Brent Roose
Alle Mitwirkenden
Unsere Arr
Klasse enthält Funktionen, die vom Arr
Helfer von Laravel kopiert wurden.
Die MIT-Lizenz (MIT). Weitere Informationen finden Sie in der Lizenzdatei.