Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Validated Dto Laravel Package

wendelladriel/laravel-validated-dto

Build typed Data Transfer Objects for Laravel that validate incoming data using familiar validation rules, defaults, and casting. Create DTOs by extending ValidatedDTO, define rules(), and get safe, validated, ready-to-use properties for your app.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Run composer require wendelladriel/laravel-validated-dto and publish the config with php artisan vendor:publish --tag="validated-dto".
  2. Create a DTO: Extend ValidatedDTO and define rules(), defaults(), and casts() methods.
    final class UserDTO extends ValidatedDTO {
        public string $name;
        public string $email;
    
        protected function rules(): array { return ['name' => 'required|string', 'email' => 'required|email']; }
        protected function defaults(): array { return []; }
        protected function casts(): array { return []; }
    }
    
  3. Instantiate: Use UserDTO::fromArray(), UserDTO::fromRequest(), or inject into controllers.
    $dto = UserDTO::fromArray(['name' => 'John', 'email' => 'john@example.com']);
    

First Use Case

Replace manual validation in controllers with DTOs. For example, replace:

$validated = request()->validate(['name' => 'required|string']);

with:

$dto = UserDTO::fromRequest(); // Automatically validates and casts

Implementation Patterns

Workflows

  1. Request Handling:

    • Inject DTOs into controllers to auto-validate requests:
      public function store(UserDTO $dto) { /* $dto is validated */ }
      
    • Use fromRequest() for manual validation:
      $dto = UserDTO::fromRequest();
      
  2. Nested Data:

    • Cast Eloquent model attributes to DTOs:
      // Model
      protected $casts = ['metadata' => MetadataDTO::class];
      
      // DTO
      final class MetadataDTO extends ValidatedDTO { ... }
      
  3. Transformation:

    • Convert DTOs to arrays, JSON, or models:
      $dto->toArray(); // ['name' => 'John', ...]
      $dto->toModel(User::class); // User instance
      
  4. Custom Logic:

    • Extend buildDataForExport() for custom transformations:
      public function toCustomFormat() {
          return (object) $this->buildDataForExport();
      }
      

Integration Tips

  • APIs: Use toJson()/toPrettyJson() for consistent API responses.
  • Forms: Validate form submissions with fromArray() or fromRequest().
  • Testing: Mock DTOs to isolate validation logic:
    $dto = new UserDTO(['name' => 'Test']);
    $this->assertEquals('Test', $dto->name);
    

Gotchas and Tips

Pitfalls

  1. Validation Rules:

    • Forgetting sometimes for optional fields causes validation errors.
    • Example: ['active' => 'sometimes|boolean'] for nullable booleans.
  2. Casting Issues:

    • Invalid formats (e.g., CarbonCast with wrong date string) throw CastException.
    • Ensure nested DTOs/collections use valid castable types.
  3. Default Values:

    • Defaults override input values if not explicitly provided.
    • Use defaults() for optional fields with fallback values.
  4. Type Safety:

    • PHP 8.0+ typed properties enforce type hints, but casting may still fail.
    • Example: public int $age requires valid integers.

Debugging

  • Validation Errors: Check ValidatedDTO::errors() for failed rules:
    try {
        $dto = UserDTO::fromArray(['email' => 'invalid']);
    } catch (\Illuminate\Validation\ValidationException $e) {
        dd($e->errors());
    }
    
  • Casting Errors: Use try-catch for CastException:
    try {
        $dto = UserDTO::fromArray(['date' => 'invalid']);
    } catch (\WendellAdriel\ValidatedDTO\Exceptions\CastException $e) {
        dd($e->getMessage());
    }
    

Tips

  1. Reuse DTOs:
    • Extend base DTOs for shared validation (e.g., BaseUserDTO).
  2. Custom Casts:
    • Implement Castable for domain-specific types:
      class CustomCast implements Castable { public function cast($value) { ... } }
      
  3. Performance:
    • Cache DTO instances for repeated use (e.g., in middleware).
  4. Documentation:
    • Use PHPDoc for DTO properties to clarify expected types/rules:
      /** @property string $name Required user name */
      public string $name;
      
  5. Testing:
    • Test edge cases (e.g., empty arrays, null values) in defaults().
    • Example:
      $this->assertNull((new UserDTO(['name' => null]))->name);
      

```markdown
### Extension Points
1. **Custom Transformers**:
   - Override `toArray()`, `toJson()`, or `buildDataForExport()` for bespoke output.
2. **Validation Extensions**:
   - Use Laravel’s validation rules (e.g., `Password`, `Unique`) in `rules()`.
3. **Event Handling**:
   - Listen to `ValidatedDTO::validated` events for post-validation logic:
     ```php
     ValidatedDTO::validated(fn (ValidatedDTO $dto) => Log::info('DTO validated', $dto->toArray()));
     ```
4. **Macros**:
   - Add static methods to `ValidatedDTO` for project-wide utilities:
     ```php
     ValidatedDTO::macro('sanitize', fn (array $data) => filter_var_array($data, FILTER_SANITIZE_STRING));
     ```
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai