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

Eloquent Typecast Laravel Package

cviebrock/eloquent-typecast

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require cviebrock/eloquent-typecast
    

    Add the trait to your Eloquent model:

    use Cviebrock\EloquentTypecast\Typecastable;
    
    class User extends Model
    {
        use Typecastable;
    }
    
  2. First Use Case: Define typecasts in your model:

    protected $typecasts = [
        'is_active' => 'boolean',
        'age' => 'integer',
        'price' => 'float',
        'created_at' => 'datetime',
    ];
    

    Now, when retrieving a User model, the attributes will automatically be cast to their specified types.


Implementation Patterns

Usage Patterns

  1. Basic Typecasting:

    protected $typecasts = [
        'active' => 'boolean',
        'user_id' => 'integer',
        'weight' => 'float',
    ];
    
    • Automatically converts database values to native PHP types when accessing attributes.
  2. Custom Casting Logic: Override the getTypecastedAttribute method for custom logic:

    public function getTypecastedAttribute($key)
    {
        if ($key === 'custom_field') {
            return strtoupper($this->attributes[$key]);
        }
        return parent::getTypecastedAttribute($key);
    }
    
  3. Dynamic Typecasting: Use a closure for dynamic casting:

    protected $typecasts = [
        'discount' => function ($value) {
            return $value / 100; // Convert percentage to decimal
        },
    ];
    

Workflows

  1. API Development: Ensure API responses return correct types without manual casting:

    return User::find(1); // Returns JSON with proper types (e.g., `is_active: true` instead of `"1"`)
    
  2. Database Migrations: Define typecasts alongside migrations to maintain consistency:

    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->boolean('is_admin')->default(false);
        $table->integer('score');
        $table->timestamps();
    });
    
    protected $typecasts = [
        'is_admin' => 'boolean',
        'score' => 'integer',
    ];
    
  3. Query Builder Integration: Use with query builder to ensure results are typecast:

    $users = User::where('age', '>', 18)->get();
    // All `age` attributes are integers, not strings.
    

Integration Tips

  1. Laravel Scout: If using Scout for search, ensure typecasts are applied before indexing:

    public function toSearchableArray()
    {
        return $this->typecasts; // Ensure proper types for search
    }
    
  2. Laravel Nova: Nova automatically respects Eloquent typecasts, so no additional setup is needed for proper field rendering.

  3. Validation: Combine with Laravel validation for seamless type handling:

    $validated = $request->validate([
        'age' => 'required|integer',
    ]);
    

Gotchas and Tips

Pitfalls

  1. MySQL Driver Quirk:

    • If using mysqlnd, typecasting may not be necessary (as noted in the README). Test thoroughly to avoid redundant casting.
  2. Closure Performance:

    • Avoid complex logic in closures for typecasts, as they run on every attribute access. Keep them simple for performance.
  3. Null Handling:

    • Closures must explicitly handle null values to avoid errors:
      'discount' => function ($value) {
          return $value ? $value / 100 : null;
      },
      
  4. Attribute Overrides:

    • If using attributes or casts in the same model, typecasts take precedence. Ensure no conflicts:
      protected $casts = ['is_active' => 'boolean']; // Overridden by typecasts
      protected $typecasts = ['is_active' => 'integer']; // Forces integer
      
  5. Database vs. PHP Types:

    • Some databases (e.g., PostgreSQL) may return boolean as t/f strings. Ensure your typecasts handle these edge cases:
      'is_active' => function ($value) {
          return $value === 't';
      },
      

Debugging

  1. Check Typecasts: Dump the model to verify casting:

    dd(User::find(1)->toArray());
    
  2. Override for Testing: Temporarily disable typecasts in tests:

    public function getTypecastedAttribute($key)
    {
        if (app()->environment('testing')) {
            return $this->attributes[$key];
        }
        return parent::getTypecastedAttribute($key);
    }
    
  3. Log Casted Values: Add debug logging to trace casting behavior:

    public function getTypecastedAttribute($key)
    {
        \Log::debug("Typecasting {$key}: " . $this->attributes[$key]);
        return parent::getTypecastedAttribute($key);
    }
    

Tips

  1. Consistent Naming: Use consistent naming for typecasts (e.g., is_active instead of active_flag) to align with Laravel conventions.

  2. Document Typecasts: Add PHPDoc comments to clarify expected types:

    /**
     * @var boolean
     */
    protected $typecasts = ['is_active' => 'boolean'];
    
  3. Leverage for APIs: Use this package to ensure API responses are type-safe, reducing client-side type juggling.

  4. Extend for Custom Types: Add support for custom types (e.g., uuid, json) by extending the trait:

    use Cviebrock\EloquentTypecast\Typecastable as BaseTypecastable;
    
    trait ExtendedTypecastable
    {
        use BaseTypecastable;
    
        protected $typecasts = [
            ...,
            'metadata' => 'json',
        ];
    
        protected function castJson($value)
        {
            return json_decode($value, true);
        }
    }
    
  5. Performance Optimization: For large datasets, cache typecast results if logic is expensive:

    protected $typecastCache = [];
    
    public function getTypecastedAttribute($key)
    {
        if (!isset($this->typecastCache[$key])) {
            $this->typecastCache[$key] = parent::getTypecastedAttribute($key);
        }
        return $this->typecastCache[$key];
    }
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
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