5

In a follow up to my earlier question, I'm focusing on cleaning up my code to keep it incredibly simple. I've moved on from the Controller and Model to the Model and Service. Typically you would have something like the following in a service method:

$record = new MyRecord();

$record->name           = $model->name;
$record->anotherField   = $model->anotherField;
// etc..

Which works and you end up defining the attributes in _attributes as an array like below:

[*:_attributes] => array
    (
        'uid' => '0'
        'name' => 'My Name'
        'anotherField' => 'Another Field'
    )

The logic that I am looking for, which I'm sure someone will tell me I am just using the wrong method, can be seen in the controller.

public function actionSave()
    {
        // require a post request
        $this->requirePostRequest();

        // assign the fields from post request
        $post = craft()->request->getPost('fields');

        // create a model, populate with the assigned fields
        $model = MyModel::populateModel($post);

        // validate attributes
        if ($model->validate()) {

            // save the record
            craft()->myPlugin->saveNew($model);

            // redirect to posted url
            $this->redirectToPostedUrl();
        }

        // grab errors from the model
        $errors = $model->getErrors();

        // return errors to the template as 'errors'
        craft()->urlManager->setRouteVariables(array(
            'errors'    => $errors
        ));
    }

In the controller code, I'm populating the model with the post with this line:

`$model = MyModel::populateModel($post);`

Is there a way to create the same behavior for the method in the service to "automagically" assign the model attributes to the $record?

2

Yii does have the equivalent populateRecord and populateRecords on CActiveRecord.

However, on both the populateModel(s) and populateRecord(s) methods, you should be very cautious of blindly mass-assigning untrusted inputs to models/records that participate in the Active Record pattern (like Craft/Yii does).

They can be susceptible to what's known as the Mass Assignment Vulnerability that many popular frameworks have been a victim of.

Yii does what it can to protect against this, but my personal preference is to explicitly assign each individual attributes on the model/record in the case of untrusted input to avoid the issue altogether.

2

Yii's setAttributes method is probably a better way to do this than the populateRecords method, as by default assignments will only be made to safe attributes.

See this wiki article, Understanding "Safe" Validation Rules , for details on how you can specify what attributes are safe to be massively assigned. This will allow you to protect against unwanted assignment from untrusted sources.

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.