Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Jan 23, 2024
1 parent 1ef1f3c commit d70d51a
Show file tree
Hide file tree
Showing 24 changed files with 327 additions and 102 deletions.
4 changes: 4 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ object, these have now been removed. Instead, you should use the new DataContext

If you were using the `DataCollectableTransformer` or `DataTransformer` then please use the `TransformedDataCollectableResolver` and `TransformedDataResolver` instead.

**Removal of `DataObject` and `DataCollectable` (Likelihood Of Impact: Low)**

If you were using the `DataObject` or `DataCollectable` interfaces then please replace the interfaces based upon the `Data` and `DataCollection` interfaces to your preference.

**Some advice with this new version of laravel-data**

We advise you to take a look at the following things:
Expand Down
33 changes: 33 additions & 0 deletions docs/advanced-usage/creating-a-cast.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,36 @@ class Email implements Castable
}
}
```

## Combining casts and transformers

You can combine casts and transformers in one class:

```php
class ToUpperCastAndTransformer implements Cast, Transformer
{
public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): string
{
return strtoupper($value);
}

public function transform(DataProperty $property, mixed $value, TransformationContext $context): string
{
return strtoupper($value);
}
}
```

Within your data object, you can use the `WithCastAndTransform` attribute to use the cast and transformer:

```php
class SongData extends Data
{
public function __construct(
public string $title,
#[WithCastAndTransform(SomeCastAndTransformer::class)]
public string $artist,
) {
}
}
```
33 changes: 33 additions & 0 deletions docs/advanced-usage/creating-a-transformer.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,36 @@ The following parameters are provided:
- **transformers** a collection of transformers that can be used to transform values

In the end, the transformer should return a transformed value.

## Combining transformers and casts

You can transformers and casts in one class:

```php
class ToUpperCastAndTransformer implements Cast, Transformer
{
public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): string
{
return strtoupper($value);
}

public function transform(DataProperty $property, mixed $value, TransformationContext $context): string
{
return strtoupper($value);
}
}
```

Within your data object, you can use the `WithCastAndTransform` attribute to use the cast and transformer:

```php
class SongData extends Data
{
public function __construct(
public string $title,
#[WithCastAndTransform(SomeCastAndTransformer::class)]
public string $artist,
) {
}
}
```
85 changes: 74 additions & 11 deletions docs/advanced-usage/internal-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ title: Internal structures
weight: 11
---

This package has some internal structures which are used to analyze data objects and their properties. They can be helpful when writing casts, transformers or rule inferrers.
This package has some internal structures which are used to analyze data objects and their properties. They can be
helpful when writing casts, transformers or rule inferrers.

## DataClass

Expand All @@ -13,51 +14,113 @@ The DataClass represents the structure of a data object and has the following pr
- `properties` all the `DataProperty`'s of the class (more on that later)
- `methods` all the magical creation `DataMethod`s of the class (more on that later)
- `constructorMethod` the constructor `DataMethod` of the class
- `isReadOnly` is the class read only
- `isAbstract` is the class abstract
- `appendable` is the class implementing `AppendableData`
- `includeable` is the class implementing `IncludeableData`
- `responsable` is the class implementing `ResponsableData`
- `transformable` is the class implementing `TransformableData`
- `validatable` is the class implementing `ValidatableData`
- `wrappable` is the class implementing `WrappableData`
- `emptyData` the the class implementing `EmptyData`
- `attributes` a collection of resolved attributes assigned to the class
- `dataCollectablePropertyAnnotations` the property annotations of the class used to infer the data collection type
- `allowedRequestIncludes` the allowed request includes of the class
- `allowedRequestExcludes` the allowed request excludes of the class
- `allowedRequestOnly` the allowed request only of the class
- `allowedRequestExcept` the allowed request except of the class
- `outputMappedProperties` properties names which are mapped when transforming the data object
- `transformationFields` structure of the transformation fields

## DataProperty

A data property represents a single property within a data object.

- `name` the name of the property
- `className` the name of the class of the property
- `type` the `DataType` of the property (more on that later)
- `validate` should the property be automatically validated
- `type` the `DataPropertyType` of the property (more on that later)
- `validate` should the property be automatically validated
- `computed` is the property computed
- `hidden` will the property be hidden when transforming the data object
- `isPromoted` is the property constructor promoted
- `isReadOnly` is the property read only
- `hasDefaultValue` has the property a default value
- `defaultValue` the default value of the property
- `cast` the cast assigned to the property
- `transformer` the transformer assigned to the property
- `inputMappedName` the name used to map a property name given
- `outputMappedName` the name used to map a property name onto
- `attributes` a collection of `ReflectionAttribute`s assigned to the property
- `attributes` a collection of resolved attributes assigned to the property

## DataMethod

A data method represents a method within a data object.

- `name` the name of the method
- `parameters` all the `DataParameter`'s of the class (more on that later)
- `parameters` all the `DataParameter`'s and `DataProperty`s of the method (more on that later)
- `isStatic` whether the method is static
- `isPublic` whether the method is public
- `isCustomCreationMethod` whether the method is a custom creation method (=magical creation method)
- `returnType` the `DataType` of the return value (more on that later)

## DataParameter

A data parameter represents a single parameter/property within a data method.

- `name` the name of the parameter
- `isPromoted` is the property/parameter constructor promoted
- `hasDefaultValue` has the parameter a default value
- `defaultValue` the default value of the parameter
- `isPromoted` is the property/parameter constructor promoted
- `type` the `DataType` of the parameter (more on that later)

## DataType

A data type represents a type within a data object.

- `Type` can be a `NamedType`, `UnionType` or `IntersectionType` (more on that later)
- `isNullable` can the type be nullable
- `isMixed` is the type a mixed type
- `isLazy` can the type be lazy
- `kind` the `DataTypeKind` of the type (more on that later)

## DataPropertyType

Extends from the `DataType` and has the following additional properties:

- `isOptional` can the type be optional
- `isDataObject` is the type a data object
- `isDataCollectable` is the type a data collection
- `dataClass` the class of the data object/collection
- `acceptedTypes` an array of types accepted by this type + their base types
- `lazyType` the class of the lazy type for the property
- `dataClass` the data object class of the property or the data object class of the collection it collects
- `dataCollectableClass` the collectable type of the data objects
- `kind` the `DataTypeKind` of the type (more on that later)

## DataTypeKind

An enum representing the kind of type of a property/parameter with respect to the package:

- Default: a non package spefic type
- DataObject: a data object
- DataCollection: a `DataCollection` of data objects
- DataPaginatedCollection: a `DataPaginatedCollection` of data objects
- DataCursorPaginatedCollection: a `DataCursorPaginatedCollection` of data objects
- DataArray: an array of data objects
- DataEnumerable: a `Enumerable` of data objects
- DataPaginator: a `Paginator` of data objects
- DataCursorPaginator: a `CursorPaginator` of data objects

## NamedType

Represents a named PHP type with the following properties:

- `name` the name of the type
- `builtIn` is the type a built-in type
- `acceptedTypes` an array of accepted types as string
- `kind` the `DataTypeKind` of the type (more on that later)
- `dataClass` the data object class of the property or the data object class of the collection it collects
- `dataCollectableClass` the collectable type of the data objects
- `isCastable` wetter the type is a `Castable`

## UnionType / IntersectionType

Represents a union or intersection of types with the following properties:

- `types` an array of types (can be `NamedType`, `UnionType` or `IntersectionType`)

60 changes: 60 additions & 0 deletions docs/advanced-usage/traits-and-interfaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Traits and interfaces
weight: 17
---

Laravel data, is built to be as flexible as possible. This means that you can use it in any way you want.

For example, the `Data` class we've been using throughout these docs is a class implementing a few data interfaces and traits:

```php
use Illuminate\Contracts\Support\Responsable;
use Spatie\LaravelData\Concerns\AppendableData;
use Spatie\LaravelData\Concerns\BaseData;
use Spatie\LaravelData\Concerns\ContextableData;
use Spatie\LaravelData\Concerns\EmptyData;
use Spatie\LaravelData\Concerns\IncludeableData;
use Spatie\LaravelData\Concerns\ResponsableData;
use Spatie\LaravelData\Concerns\TransformableData;
use Spatie\LaravelData\Concerns\ValidateableData;
use Spatie\LaravelData\Concerns\WrappableData;
use Spatie\LaravelData\Contracts\AppendableData as AppendableDataContract;
use Spatie\LaravelData\Contracts\BaseData as BaseDataContract;
use Spatie\LaravelData\Contracts\EmptyData as EmptyDataContract;
use Spatie\LaravelData\Contracts\IncludeableData as IncludeableDataContract;
use Spatie\LaravelData\Contracts\ResponsableData as ResponsableDataContract;
use Spatie\LaravelData\Contracts\TransformableData as TransformableDataContract;
use Spatie\LaravelData\Contracts\ValidateableData as ValidateableDataContract;
use Spatie\LaravelData\Contracts\WrappableData as WrappableDataContract;

abstract class Data implements Responsable, AppendableDataContract, BaseDataContract, TransformableDataContract, IncludeableDataContract, ResponsableDataContract, ValidateableDataContract, WrappableDataContract, EmptyDataContract
{
use ResponsableData;
use IncludeableData;
use AppendableData;
use ValidateableData;
use WrappableData;
use TransformableData;
use BaseData;
use EmptyData;
use ContextableData;
}
```

These traits and interfaces allow you to create your own versions of the base `Data` class, and add your own functionality to it.

An example of such custom base data classes are the `Resource` and `Dto` class.

Each interface (and corresponding trait) provides a piece of functionality:

- **BaseData** provides the base functionality of the data package to create data objects
- **BaseDataCollectable** provides the base functionality of the data package to create data collections
- **ContextableData** provides the functionality to add context for includes and wraps to the data object/collectable
- **IncludeableData** provides the functionality to add includes, excludes, only and except to the data object/collectable
- **TransformableData** provides the functionality to transform the data object/collectable
- **ResponsableData** provides the functionality to return the data object/collectable as a response
- **WrappableData** provides the functionality to wrap the transformed data object/collectable
- **AppendableData** provides the functionality to append data to the transformed data payload
- **EmptyData** provides the functionality to get an empty version of the data object
- **ValidateableData** provides the functionality to validate the data object
- **DeprecatableData** provides the functionality to add deprecated functionality to the data object
1 change: 0 additions & 1 deletion docs/as-a-data-transfer-object/creating-a-data-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,3 @@ class SongData extends Dto
The `Dto` class is a data class in its most basic form. It can br created from anything using magical methods, can
validate payloads before creating the data object and can be created using factories. But it doesn't have any of the
other functionality that the `Data` class has.

24 changes: 24 additions & 0 deletions docs/as-a-data-transfer-object/factories.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,27 @@ SongData::factory()->withCast('string', StringToUpperCast::class)->from(['title'
These casts will not replace the other global casts defined in the `data.php` config file, they will though run before
the other global casts. You define them just like you would define them in the config file, the first parameter is the
type of the property that should be cast and the second parameter is the cast class.

## Using the creation context

Internally the package uses a creation context to create data objects. The factory allows you to use this context manually, but when using the from method it will be used automatically.

It is possible to inject the creation context into a magical method by adding it as a parameter:

```php
class SongData extends Data
{
public function __construct(
public string $title,
public string $artist,
) {
}

public static function fromModel(Song $song, CreationContext $context): self
{
// Do something with the context
}
}
```

You can read more about creation contexts [here](/docs/laravel-data/v4/advanced-usage/pipeline.md).
2 changes: 1 addition & 1 deletion src/Attributes/DataCollectionOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public function __construct(
public string $class
) {
if (! is_subclass_of($this->class, BaseData::class)) {
throw new CannotFindDataClass("Class {$this->class} given does not implement `DataObject::class`");
throw new CannotFindDataClass("Class {$this->class} given does not implement `BaseData::class`");
}
}
}
2 changes: 0 additions & 2 deletions src/Concerns/EnumerableMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

namespace Spatie\LaravelData\Concerns;

use Spatie\LaravelData\Contracts\DataCollectable;
use Spatie\LaravelData\DataCollection;

/**
* @template TKey of array-key
* @template TValue
*
* @implements \ArrayAccess<TKey, TValue>
* @implements DataCollectable<TValue>
*/
trait EnumerableMethods
{
Expand Down
17 changes: 0 additions & 17 deletions src/Contracts/DataCollectable.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/Contracts/DataObject.php

This file was deleted.

Loading

0 comments on commit d70d51a

Please sign in to comment.