2

I have a model that contains a bunch of storage arrays where I collect results from various services I have written.

class Shipper_ResultsModel extends BaseModel
{

shipping categories for debugging

    protected function defineAttributes()
    {
        return array(
            'service'               => array('type'=>AttributeType::Enum, 'values'=>['post','courier','free','cantShip','needsQuote']),
            'options'               => array('type'=>AttributeType::Mixed,'default'=>[]),
            'boxes'                 => array('type'=>AttributeType::Mixed,'default'=>[]),
            'postShippingItems'     => array('type'=>AttributeType::Mixed,'default'=>[]),
            'courierShippingItems'  => array('type'=>AttributeType::Mixed,'default'=>[]),
            'freeShippingItems'     => array('type'=>AttributeType::Mixed,'default'=>[]),
            'cantShippingItems'     => array('type'=>AttributeType::Mixed,'default'=>[]),
            'quoteShippingItems'    => array('type'=>AttributeType::Mixed,'default'=>[]),
        );
    }

Each of this ShippingItems arrays is intended to hold an array of Shipper_ShippingItem models.

My issue is in building these arrays, I create new items and add them like this:

            $shippingItem = Shipper_ShippingItemModel::populateModel($data);

            //build our arrays of items
            if($shippingClass=="Courier Only"){
                $results->courierShippingItems[] = $shippingItem;
            }

But this results in the following error:

PHP Notice: Indirect modification of overloaded property Craft\Shipper_ResultsModel::$courierShippingItems has no effect

I think this is because I am not using array objects as such but I have to say I've got a little confused here and various syntax experiments have resulted in ignoble failures.

Some guidance as to the right way would be much appreciated (and am I right in using AttributeType::Mixed for these?)

(This is all for a mega shipping calculator for Craft Commerce, should that matter)

2

I'm pretty sure 'default'=>[] isn't doing anything so it's probably not necessary.

If you wanted to force a single attribute to be of a specific model, you could use:

'courierShippingItems'  => array('type' => AttributeType::Mixed, 'model' => 'Shipper_ShippingItemModel');

Regardless, you'll want to use BaseModel's setAttribute to do what you're trying to do and build your entire array up first before assigning it to the attribute. Something like this:

$shippingItems[] = Shipper_ShippingItemModel::populateModel($data);

$results->setAttribute('courierShippingItems', $shippingItems);
| improve this answer | |
  • 1
    Thanks Brad - I am now doing it like this, although simply building the array in a separate variable, and then assigning it directly at the end, rather than using setAttribute, appears to work fine as well. – Jeremy Daalder Sep 28 '15 at 23:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.