Is there are reason why you are doing this? You can’t throw multiple exceptions like that in one go. Also, I don’t think you should be throwing exceptions in the first place for validation errors.
In fact my data come from a form without validation. So, in my controller, if an error appears during saving the object, I want give a reason to my user (In my example, the port number entered in my form is not an integer).
My controller is called with Ajax and return result with a json object.
Indeed CActiveForm::validate() return what I want.
However, my form send me several object to insert in my database. So here is my controller:
public function actionSaveSiteInformation()
{
$result=array();
if(isset($_POST['network']))
{
foreach ($_POST['network'] as $key=>$network_form)
{
$network=new t_network;
$network->attributes=$network_form;
$errors=CActiveForm::validate($network);
if($errors !== '[]')
$result['network'][$key]=json_decode ($errors);
else
$network->save();
}
}
if(isset($_POST['server']))
...//same code than network
echo json_encode(['result' => $result]);
}
So i’m obliged to do a json_decode the result of validate() to encode it again at the end of my controller… Not very smart. Do you see a better solution?
I think by default, CActiveForm::validate() does not require you to populate the model’s attributes. Its 3rd parameter ($loadInput) is by default set to true and with that, force loads all POST data with the same name as your model’s class. This works fine with single models, not sure if it negatively affects arrays of the same model. Might be safer to set that parameter to false if you are populating the attributes yourself.
For an array of models, you could probably use CActiveForm::validateTabular()
You also might want to validate all your models first before saving (instead of validate -> save, validate -> save, etc), unless you are ok with some models failing validation and other going through just fine.
I’ve never tried validateTabular() but I’m used to just concatenating the model validation outputs, something like:
public function actionSaveSiteInformation()
{
$result = array();
if (isset($_POST['network'])) {
// a boolean variable holding the global validation result
$valid = true;
// a string variable holding the global validation errors if applicable
$validationOutput = '';
foreach ($_POST['network'] as $key => $network_form) {
$network = new t_network;
$network->attributes = $network_form;
if (!$network->validate()) {
$valid &= false;
$validationOutput .= preg_replace('/network_/', 'network_' . $key . '_', CActiveForm::validate(t_network);
}
}
if ($valid) {
…
} else {
// echo the validation errors and end
echo $validationOutput;
Yii::app()->end();
}
}
}