Optional required model fields.

Hello.

I faced some scenario that needs a lot of spare coding.

Imagine you have a signup formhaving 3 mandatory fields:

  • username

  • password

  • password_repeat

However, customer says he may optionally need the following:

  • Full name

  • Agreement checkbox

  • Captcha

My question is: what is the best practice to achieve this in

less code? It’s obvious this should be bound to a model. Most

likely, a behavior.

Common functionality for $useCaptcha = true; controller’s property

would be:

  • prevent validation, see CModel::validate($attributes)

  • prevent attribute assignment even if it’s safe

  • prevent form field rendering in a view

This is what I have in a code right now. It’s not clean and is spread

over controller / views (this is actually a controller’s action):




            // Populate a list of attributes to validate.

            $attributes = array_flip($form->getSafeAttributeNames());

            

            // ... and exclude hidden attributes.

            if (!$this->useName) unset($attributes['name'], $data['name']);

            if (!$this->useAgreement) unset($attributes['agreement'], $data['agreement']);

            if (!$this->useCaptcha) unset($attributes['captcha'], $data['captcha']);

            

            // Set form data.

            $form->setAttributes($data);


            if ($form->validate(array_keys($attributes)) {...}




Thanks in advance for your feedback! :)

Hi waylex,

it seems like a typical case for using model scenario.

ciao

B)

Well, this might be done if we could apply multiple scenarios to the model.

Otherwise (in this particular case) we need to create 7 different scenarios

for all property combinations:

use_name

use_agreement

use_captcha

use_name_agreement

use_name_captcha

use_agreement_captcha

use_name_agreement_captcha

Then we’ll need to write code for genearting these scenario names from 3 props:

$useName, $useAgreement, $useCaptcha. This is not the way thiings should work :)

And still we need controller’s property to use it in a view. I start to think of

an additional CModel method: setUnsafeAttributes(). It should override rules()

attribute safety rules and would do the job! In a view we could do the following:




if ($model->isAttributeSafe('captcha')) {

// Render our captcha field...

}



I think this should become a ticket! :)