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

Model Casts Laravel Package

neuecommerce/model-casts

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require neuecommerce/model-casts
    

    Publish the config (if available) with:

    php artisan vendor:publish --provider="NeueCommerce\ModelCasts\ServiceProvider"
    
  2. First Use Case Define a cast in your Eloquent model:

    use NeueCommerce\ModelCasts\Casts\JsonArray;
    use NeueCommerce\ModelCasts\Casts\Boolean;
    
    class Product extends Model
    {
        protected $casts = [
            'options' => JsonArray::class,
            'is_active' => Boolean::class,
        ];
    }
    
    • Test it: Save a model with JSON data or a boolean value, then retrieve it to verify automatic casting.
  3. Where to Look First

    • Casts Directory: Explore vendor/neuecommerce/model-casts/src/Casts/ for available cast types.
    • Documentation: Check for inline PHPDoc comments in the cast classes (if any).
    • Config: Review published config (if applicable) for default behaviors or customizations.

Implementation Patterns

Common Workflows

  1. Basic Casting Use built-in casts like Boolean, JsonArray, or DateTime for common data transformations:

    protected $casts = [
        'published_at' => \NeueCommerce\ModelCasts\Casts\DateTime::class,
        'tags' => \NeueCommerce\ModelCasts\Casts\JsonArray::class,
    ];
    
  2. Customizing Casts Extend existing casts for domain-specific logic:

    use NeueCommerce\ModelCasts\Casts\JsonArray;
    
    class CustomJsonArray extends JsonArray
    {
        public function get($model, string $key, $value, array $attributes)
        {
            return parent::get($model, $key, $array = json_decode($value, true), $attributes);
        }
    }
    

    Register the custom cast in your model:

    protected $casts = [
        'metadata' => CustomJsonArray::class,
    ];
    
  3. Integration with API Resources Leverage casts to simplify API responses:

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'options' => $this->options, // Automatically cast to array
            'is_active' => $this->is_active, // Automatically cast to bool
        ];
    }
    
  4. Mass Assignment Use casts to sanitize or transform input during create/update:

    $product = Product::create([
        'options' => '{"size":"large","color":"red"}', // Casts to array
        'is_active' => 'yes', // Casts to boolean
    ]);
    
  5. Database Storage Optimization Store complex data as JSON (e.g., tags, metadata) and cast to arrays/objects in PHP:

    protected $casts = [
        'config' => \NeueCommerce\ModelCasts\Casts\Json::class,
    ];
    
  6. Relationships with Casts Cast attributes of related models:

    public function user()
    {
        return $this->belongsTo(User::class)->withDefault([
            'is_admin' => false, // Casted via Boolean cast
        ]);
    }
    

Integration Tips

  • Laravel Version Compatibility: Ensure compatibility with your Laravel version (e.g., 8.x, 9.x).
  • Database Schema: Design schemas to store casted data efficiently (e.g., JSON column for JsonArray).
  • Testing: Test edge cases like null values, malformed JSON, or invalid booleans.
  • Performance: Avoid overusing casts for heavy transformations; keep logic simple.

Gotchas and Tips

Pitfalls

  1. Malformed JSON

    • Issue: JsonArray or Json casts may throw exceptions on invalid JSON.
    • Fix: Use json_decode($value, true) with error suppression or a custom cast:
      class SafeJsonArray implements CastsAttributes
      {
          public function get($model, string $key, $value, array $attributes)
          {
              return json_decode($value, true) ?: [];
          }
      }
      
  2. Boolean Cast Ambiguity

    • Issue: Strings like "0", "1", "false", or "true" may not cast as expected.
    • Fix: Customize the Boolean cast or pre-process input:
      $isActive = filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN);
      
  3. Database-Level Constraints

    • Issue: Storing JSON in a non-JSON column (e.g., TEXT) may cause issues.
    • Fix: Use JSON or LONGTEXT columns for JSON casts.
  4. Circular References in JSON

    • Issue: JsonArray may fail on circular references in nested data.
    • Fix: Use JSON_UNESCAPED_UNICODE or a custom cast with json_encode($value, JSON_THROW_ON_ERROR).
  5. Overriding Default Casts

    • Issue: Accidentally overriding Laravel’s built-in casts (e.g., date).
    • Fix: Prefix custom casts (e.g., custom_date) or use fully qualified namespaces.
  6. Performance with Large JSON

    • Issue: Casting large JSON strings may impact performance.
    • Fix: Consider storing only necessary fields or using a dedicated JSON column.

Debugging Tips

  • Log Casted Values: Add debug logs to inspect casted attributes:
    $model->setAttribute('options', $value);
    \Log::debug('Casted options:', [$model->options]);
    
  • Check Cast Order: Casts are applied in the order defined in $casts. Reorder if dependencies exist.
  • Use getAttribute: Override getAttribute to debug casting logic:
    public function getAttribute($key)
    {
        \Log::debug("Getting attribute $key", [parent::getAttribute($key)]);
        return parent::getAttribute($key);
    }
    

Extension Points

  1. Create Custom Casts Implement the CastsAttributes interface:

    use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
    
    class CustomCast implements CastsAttributes
    {
        public function get($model, string $key, $value, array $attributes)
        {
            // Decoding logic
        }
    
        public function set($model, string $key, $value, array $attributes)
        {
            // Encoding logic
        }
    }
    
  2. Modify Existing Casts Extend base casts (e.g., Boolean, JsonArray) to add validation or formatting:

    class ValidatedJsonArray extends JsonArray
    {
        public function set($model, string $key, $value, array $attributes)
        {
            if (!is_array($value)) {
                throw new \InvalidArgumentException("Value must be an array.");
            }
            return parent::set($model, $key, $value, $attributes);
        }
    }
    
  3. Global Cast Registration Register casts globally in the service provider:

    use Illuminate\Database\Eloquent\Casts\Attribute;
    
    public function boot()
    {
        Attribute::macro('customCast', function ($cast) {
            return new $cast();
        });
    }
    

    Usage:

    protected $casts = [
        'data' => Attribute::customCast(CustomCast::class),
    ];
    
  4. Conditional Casting Dynamically apply casts based on conditions:

    public function getCasts($model)
    {
        $casts = [
            'options' => $model->is_premium ? JsonArray::class : 'array',
        ];
        return $casts;
    }
    

Config Quirks

  • Default Values: Some casts may ignore default values in $attributes. Explicitly set defaults in the model:
    protected $attributes = [
        'is_active' => false,
    ];
    
  • Nullable Casts: Ensure casts handle null values gracefully (e.g., return null or a default).
  • Serialization: Casts may affect JSON API responses or serialization (e.g., toJson()). Test thoroughly.
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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