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 Lift Laravel Package

wendelladriel/laravel-lift

Experimental Laravel package that supercharges Eloquent models with typed public properties matching your schema, powered by PHP 8 attributes. Add validation rules and other metadata directly on models and access them via handy methods, using Eloquent events for easy drop-in use.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation: Add via Composer:
    composer require wendelladriel/laravel-lift
    
  2. Basic Usage: Apply the Lift trait to a model and define typed public properties with attributes:
    use WendellAdriel\Lift\Lift;
    use WendellAdriel\Lift\Attributes\Fillable;
    use WendellAdriel\Lift\Attributes\Rules;
    
    final class Product extends Model
    {
        use Lift;
    
        #[Fillable]
        #[Rules(['required', 'string'])]
        public string $name;
    }
    
  3. First Use Case: Replace create() with castAndCreate() for automatic casting:
    $product = Product::castAndCreate(['name' => 'Test Product']);
    

Where to Look First

  • Documentation: Start with Lift’s official docs for attribute reference.
  • Attributes: Focus on Cast, Fillable, and Rules for initial adoption.
  • Migration: Gradually replace fillable, casts, and rules arrays with attributes.

Implementation Patterns

Workflows

  1. Model Definition:

    • Use attributes (e.g., #[Cast('float')]) instead of $casts array.
    • Example:
      #[Fillable]
      #[Cast('float')]
      #[Rules(['min:0'])]
      public float $price;
      
    • Benefit: Type safety and IDE autocompletion (e.g., $product->price is float).
  2. Data Handling:

    • Replace Eloquent methods with Lift’s typed variants:
      • create()castAndCreate()
      • fill()castAndFill()
      • update()castAndUpdate()
    • Example:
      $product->castAndFill(['price' => '19.99']); // Automatically casts to float
      
  3. Relationships:

    • Define relationships via attributes (e.g., #[BelongsTo(User::class)]).
    • Tip: Use #[HasManyThrough] for complex relationships without methods.
  4. Immutable Properties:

    • Mark critical fields as immutable to prevent runtime changes:
      #[Immutable]
      #[Fillable]
      public string $sku;
      
    • Use Case: Audit logs or reference data (e.g., tax IDs).
  5. Event-Driven Logic:

    • Attach custom events to property changes:
      #[Watch(PriceUpdatedEvent::class)]
      public float $price;
      
    • Pattern: Dispatch events in booted() or use Observers for side effects.

Integration Tips

  • Hybrid Approach: Mix attributes with traditional Eloquent config (e.g., keep $guarded in array format).
  • Testing: Use castAndFill() in unit tests to ensure type safety:
    $product = new Product();
    $product->castAndFill(['price' => 'invalid']); // Fails validation early
    
  • Migrations: Update database columns to match attribute defaults (e.g., #[Column(default: 0.0)]).
  • API Resources: Leverage typed properties for consistent JSON responses:
    public function toArray(): array
    {
        return [
            'name' => $this->name,
            'price' => $this->price, // Always returns float
        ];
    }
    

---

## Gotchas and Tips

### Pitfalls
1. **Attribute Order Matters**:
   - Place `#[Fillable]` **before** `#[Rules]` or `#[Cast]` to avoid conflicts.
   - **Example**:
     ```php
     #[Fillable]       // ✅ Correct
     #[Rules(['required'])]
     public string $name;
     ```

2. **Immutable Properties**:
   - **Exception**: `ImmutablePropertyException` is thrown **after** `save()`, not during `fill()`.
   - **Workaround**: Validate immutability in `booted()`:
     ```php
     protected static function booted(): void
     {
         static::updating(function (self $model) {
             if ($model->isDirty('sku')) {
                 throw new \RuntimeException('SKU cannot be modified.');
             }
         });
     }
     ```

3. **Casting Quirks**:
   - **JSON Columns**: Use `#[Cast('array')]` for JSON fields, but ensure database column is `json` or `text`.
   - **Carbon Casting**: `immutable_datetime` requires `CarbonImmutable` type hint:
     ```php
     #[Cast('immutable_datetime')]
     public CarbonImmutable $created_at;
     ```

4. **Relationship Pitfalls**:
   - **Attribute vs. Method**: Attributes **override** method-defined relationships.
   - **Debugging**: Use `dd($model->relations)` to inspect dynamically generated relationships.

5. **Performance**:
   - **Attribute Parsing**: Lift processes attributes on model instantiation. Avoid overusing on large models.
   - **Event Overhead**: `#[Watch]` events fire per-property; batch updates may trigger multiple events.

### Debugging Tips
1. **Attribute Validation**:
   - Check for typos in attribute names (e.g., `#[Cast]` vs. `#[CastAttribute]`).
   - Use `php artisan lift:debug` (if available) or dump the model’s `$attributes` array.

2. **Casting Issues**:
   - **Symptom**: Property remains `null` or wrong type after `castAndFill()`.
   - **Fix**: Verify the cast type matches the property type hint (e.g., `float` vs. `double`).

3. **Immutable Errors**:
   - **Symptom**: `ImmutablePropertyException` in unexpected places.
   - **Debug**: Temporarily remove `#[Immutable]` to isolate the issue.

4. **Relationship Errors**:
   - **Symptom**: `RelationNotFoundException` for attribute-defined relationships.
   - **Fix**: Ensure the target model’s table/foreign keys match the attribute config.

### Extension Points
1. **Custom Attributes**:
   - Extend Lift by creating new attributes (e.g., `#[Encrypt]` for sensitive fields).
   - **Example**:
     ```php
     #[Attribute]
     public function Encrypt(): void { /* Logic */ }
     ```

2. **Global Configuration**:
   - Override default behavior in `config/lift.php` (if supported in future versions).
   - **Current Workaround**: Use model boot events:
     ```php
     Product::booting(function () {
         // Modify Lift behavior globally
     });
     ```

3. **Testing Helpers**:
   - Create a trait for test models to skip Lift processing:
     ```php
     trait SkipLift
     {
         public function __construct(array $attributes = [])
         {
             parent::__construct($attributes);
             $this->skipLiftProcessing = true;
         }
     }
     ```

4. **Database Schema**:
   - Use `Schema::table()` to align columns with attribute defaults (e.g., `default: 0.0`).
   - **Example**:
     ```php
     Schema::table('products', function (Blueprint $table) {
         $table->float('price')->default(0.0);
     });
     ```

### Pro Tips
- **IDE Support**: Use PHPStorm’s "Generate PHPDoc" to auto-document typed properties.
- **Migration Strategy**: Start with non-critical models (e.g., `Product`) before applying to core models.
- **Validation**: Combine `#[Rules]` with Laravel’s validation for complex logic:
  ```php
  #[Rules(['required', 'custom:unique_name'])]
  public string $name;
  • Legacy Code: Use #[Column] to map public properties to existing database columns without renaming.
  • Performance: For read-heavy models, cache relationship results:
    #[HasMany(Comment::class)]
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class)->withTimestamps();
    }
    
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