Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Model casts not working properly

I am currently working on my Laravel application but I am running into a problem.

I have a model called StoreDataProduct which has two casts

protected $casts = [
    'default_image' => 'array',
    'images'        => 'array',
];

Now in two places of my application, this model is not working correctly with the casts. Firstly in an update method somewhere I turn the model into an array to quickly update all changed values.

$productArray = $currentStoreDataProduct->toArray();

But it throws an error that json_decode expects a string but gets an array.

Secondly, I am trying to get the property of a product and put it in an array somewhere else in my application but it throws the same error.

'default_image'          => $currentStoreDataProduct->default_image,

Any help with this problem would be appreciated.

dd of the model->getAttributes:

array:33 [
"store_data_product_id" => 12204
  "website_id" => 5
  "store_view_id" => 13
  "store_data_brand_id" => null
  "store_data_supplier_id" => null
  "external_product_id" => 70432304
  "external_variant_id" => 139154696
  "name" => "ONE + Kreissäge 150mm RWSL1801M *Body only*"
  "name_long" => "ONE + Kreissäge 150mm RWSL1801M *Body only*"
  "name_variant" => "Default"
  "description" => "ONE + Circular saw 150mm RWSL1801M *Body only*. Ideal for sawing panels, chipboards, laminated boards and wood materials. The integrated laser ensures more exact longitudinal cuts. The thin carbide saw blade ensures less resistance during sawing and a longer service life of the hand-held circular saw."
  "content" => """
    <p>*Body only*</p>\r\n
    <p>Ideal for sawing panels, chipboards, laminated boards and wood materials. The integrated laser ensures more exact longitudinal cuts. The thin carbide saw blade ensures less resistance during sawing and a longer service life of the hand-held circular saw. One Plus is the most flexible battery tool system in the world, allowing you to use 29 different cordless power tools and 7 different garden tools with just one battery and charger. The flexibility of One Plus means for you that you can put together your own cordless tool system, entirely to your wishes, how and when you want. Invest once in a battery and charger, choose the tools you need and you can use all the tools with this one battery. You save money because you do not have to buy a battery and charger with every new tool!</p>\r\n
    <h3>Highlights &amp; Details</h3>\r\n
    <ul class="product-features list--unstyled">\r\n
    <li class="product-features__item">Micro softgrip</li>\r\n
    <li class="product-features__item">Laser for more exact longitudinal cuts</li>\r\n
    </ul>\r\n
    <h3>Performance</h3>\r\n
    <ul class="product-features list--unstyled">\r\n
    <li class="product-features__item">Laser for more exact longitudinal cuts</li>\r\n
    <li class="product-features__item">Cutting capacity of 45 mm at 90 °</li>\r\n
    <li class="product-features__item">Miter adjustment up to 50 °</li>\r\n
    <li class="product-features__item">Thin hard metal saw blade (1.5 mm)</li>\r\n
    <li class="product-features__item">Spindle lock for simple saw blade change</li>\r\n
    <li class="product-features__item">Micro softgrip.</li>\r\n
    </ul>\r\n
    <h3>Delivery</h3>\r\n
    <ul class="product-features list--unstyled">\r\n
    <li class="product-features__item">Tungsten carbide saw blade Z 18 Ø 150 mm</li>\r\n
    <li class="product-features__item">Parallel stop</li>\r\n
    <li class="product-features__item">Allen key.</li>\r\n
    </ul>
    """
  "url" => "one-cirkelzaag-150mm-70432304"
  "default_image" => "{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397588\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397588\/50x50x2\/file.jpg"}"
  "images" => "{"171826733":{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397597\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397597\/50x50x2\/file.jpg"},"171826727":{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397594\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397594\/50x50x2\/file.jpg"},"171826721":{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397588\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397588\/50x50x2\/file.jpg"},"171826712":{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397576\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397576\/50x50x2\/file.jpg"},"171826709":{"src":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397567\/file.jpg","thumb":"https:\/\/cdn.webshopapp.com\/shops\/38604\/files\/193397567\/50x50x2\/file.jpg"}}"
  "meta_fields" => null
  "article_code" => "140-0075"
  "sku" => "5133001164"
  "ean" => "4892210118554"
  "cost_price_excl" => "58.82"
  "price_excl" => "78.4298"
  "special_price_excl" => "0"
  "vat_rate" => "1.21"
  "is_default" => true
  "sort_order" => 1
  "visibility" => "visible"
  "stock_level" => 998
  "stock_sold" => 1
  "stock_status" => "enabled"
  "weight" => 0
  "settings" => "{"has_been_salable":1,"last_date_salable":{"date":"2018-05-14 08:44:30.884906","timezone_type":3,"timezone":"Europe\/Amsterdam"},"fiction_margin":0}"
  "created_at" => "2018-05-12 00:06:07"
  "updated_at" => "2018-05-14 10:06:07"
]

Part of the logged error:

    [2018-05-14 10:15:22] local.ERROR: json_decode() expects parameter 1 to be string, array given {"exception":"[object] (ErrorException(code: 0): json_decode() expects parameter 1 to be string, array given at /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:682)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'json_decode() e...', '/var/www/domain...', 682, Array)
#1 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(682): json_decode(Array, true)
#2 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(491): Illuminate\\Database\\Eloquent\\Model->fromJson(Array)
#3 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(182): Illuminate\\Database\\Eloquent\\Model->castAttribute('default_image', Array)
#4 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(102): Illuminate\\Database\\Eloquent\\Model->addCastAttributesToArray(Array, Array)
#5 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(972): Illuminate\\Database\\Eloquent\\Model->attributesToArray()
like image 598
Ferdi van der Woerd Avatar asked Oct 17 '22 18:10

Ferdi van der Woerd


1 Answers

I found out what causes the error. I call the model by combining some data from different tables and hydrating that into a model, but by doing this the returned model contains the properties already casted because it sets them like this.

public function setRawAttributes(array $attributes, $sync = false)
    {
        $this->attributes = $attributes;

        if ($sync) {
            $this->syncOriginal();
        }

        return $this;
    }

That's why I am getting the error since it's already an array for this newly returned model.

I eventually solved this error by calling getAttributes on the merged model instead of toArray. That way the attributes are set on the returning model as they are meant to be set (JSON instead of as an array).

like image 68
Ferdi van der Woerd Avatar answered Oct 20 '22 22:10

Ferdi van der Woerd