Ok, of course.
We have main model, Ancestors.php
<?php
/**
* This is the model class for table "{{ancestors}}".
*
* The followings are the available columns in table '{{ancestors}}':
* @property string $id
* @property string $name
* @property string $surname
*/
class Ancestors extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return '{{ancestors}}';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('name, surname', 'length', 'max'=>255),
array('name', 'required'),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('id, name, surname', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'events'=>array(self::HAS_MANY, 'Events', 'ancestor_id'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'name' => 'Name',
'surname' => 'Surname',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id,true);
$criteria->compare('name',$this->name,true);
$criteria->compare('surname',$this->surname,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* @param string $className active record class name.
* @return Ancestors the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
The other model is Events.php
<?php
/**
* This is the model class for table "{{events}}".
*
* The followings are the available columns in table '{{events}}':
* @property string $id
* @property integer $type_id
* @property string $type_string
* @property integer $ancestor_id
* @property integer $year
* @property integer $month
* @property integer $day
* @property string $julianday_min
* @property string $julianday_max
* @property string $place
* @property integer $parish_id
*/
class Events extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return '{{events}}';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
// tolgo required fields per aggirare ostacoli nei form !!!
// array('type_string, ancestor_id, julianday_min, julianday_max', 'required'),
array('type_id, ancestor_id, year, month, day, parish_id', 'numerical', 'integerOnly'=>true),
array('day', 'numerical', 'min'=>1, 'max'=>31, 'allowEmpty'=>true),
array('month', 'numerical', 'min'=>1, 'max'=>12, 'allowEmpty'=>true),
array('type_string', 'length', 'max'=>4),
array('julianday_min, julianday_max', 'length', 'max'=><img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='8)' />,
array('place', 'length', 'max'=>255),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('id, type_id, type_string, ancestor_id, year, month, day, julianday_min, julianday_max, place, parish_id', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'parish'=>array(self::BELONGS_TO, 'Parishes', 'parish_id'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'type_id' => 'Type',
'type_string' => 'Type String',
'ancestor_id' => 'Ancestor',
'year' => 'Year',
'month' => 'Month',
'day' => 'Day',
'julianday_min' => 'Julianday Min',
'julianday_max' => 'Julianday Max',
'place' => 'Place',
'parish_id' => 'Parish',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id,true);
$criteria->compare('type_id',$this->type_id);
$criteria->compare('type_string',$this->type_string,true);
$criteria->compare('ancestor_id',$this->ancestor_id);
$criteria->compare('year',$this->year);
$criteria->compare('month',$this->month);
$criteria->compare('day',$this->day);
$criteria->compare('julianday_min',$this->julianday_min,true);
$criteria->compare('julianday_max',$this->julianday_max,true);
$criteria->compare('place',$this->place,true);
$criteria->compare('parish_id',$this->parish_id);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* @param string $className active record class name.
* @return Events the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
We have AncestorsController.php (I show you only until actionCreate, because I’ll work for actionUpdate only when create is ok)
class AncestorsController extends Controller
{
/**
* @var string the default layout for the views. Defaults to '//layouts/column2', meaning
* using two-column layout. See 'protected/views/layouts/column2.php'.
*/
public $layout='//layouts/column2';
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
'postOnly + delete', // we only allow deletion via POST request
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('@'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
'users'=>array('admin'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
/**
* Displays a particular model.
* @param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$model = new Ancestors;
$event_model = array();
$event_model[] = new Events;
$event_model[] = new Events;
$event_model[] = new Events;
// Uncomment the following line if AJAX validation is needed
//$this->performAjaxValidation($model);
if(!empty($_POST))
{
// Set attribute for ancestor
$model->attributes=$_POST['Ancestors'];
// Set attribute for events
foreach ($event_model as $k => $event) {
$event_model[$k]->attributes = $_POST['Events'][$k];
}
// Validate all models
$valid=$model->validate();
foreach ($event_model as $k => $event) {
/*
$valid=$event_model[$k]->validate() && $valid;
*/
$event_model[$k]->validate();
$event_errors = $event_model[$k]->getErrors();
var_dump($event_errors);
if (empty($event_errors)) {
$valid = $valid && true;
} else {
$valid = $valid && false;
}
}
if($valid)
{
// save main model
$model->save();
// ATTENTION: To get ancestor_id we need to save it before...
// set foreign keys for event models
$ancestor_id = $model->id;
$event_model[0]->type_string = 'BIRT';
$event_model[1]->type_string = 'BAPT';
$event_model[2]->type_string = 'DEAT';
foreach ($event_model as $k => $event) {
$event_model[$k]->type_id = $k+1;
$event_model[$k]->ancestor_id = $ancestor_id;
}
// set julian days
// WIP to avoid errors...
/*
$event_model_1->julianday_min = gregoriantojd ($event_model_1->month , $event_model_1->day , $event_model_1->year);
$event_model_1->julianday_max = gregoriantojd ($event_model_1->month , $event_model_1->day , $event_model_1->year);
$event_model_2->julianday_min = gregoriantojd ($event_model_2->month , $event_model_2->day , $event_model_2->year);
$event_model_2->julianday_max = gregoriantojd ($event_model_2->month , $event_model_2->day , $event_model_2->year);
*/
// save event models
foreach ($event_model as $k => $event) {
// check before save
if ( ($event_model[$k]->place!=null) || ($event_model[$k]->parish_id > 0) || ($event_model[$k]->day!=null) || ($event_model[$k]->month!=null) || ($event_model[$k]->year!=null) )
{
$event_model[$k]->save();
}
}
// save contribute
$contribution = new Contributions;
$contribution->contribution_type = 'CREATE';
$contribution->user_id = Yii::app()->user->getId();
$contribution->username = Yii::app()->user->name;
$contribution->object_type = 'Ancestors';
$contribution->object_id = $model->id;
$contribution->submit_time = time();
// save without validation
$contribution->save(false);
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('create',array(
'model'=>$model,
'event_model[0]'=>$event_model[0],
'event_model[1]'=>$event_model[1],
'event_model[2]'=>$event_model[2],
));
}
[b]
This is the form where I collect data (Ancestors form)[/b]
<?php
/* @var $this AncestorsController */
/* @var $model Ancestors */
/* @var $form CActiveForm */
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'ancestors-form',
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php
$event_model=array();
$event_model[]=new Events;
$event_model[]=new Events;
$event_model[]=new Events;
//echo $form->errorSummary($model);
echo $form->errorSummary($model);
echo $form->errorSummary($event_model[0]);
echo $form->errorSummary($event_model[1]);
echo $form->errorSummary($event_model[2]);
?>
<div class="row">
<?php echo $form->labelEx($model,'name'); ?>
<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'name'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'surname'); ?>
<?php echo $form->textField($model,'surname',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'surname'); ?>
</div>
<?php
if ((isset($_POST['Events'])) && (sizeof($_POST['Events'])>0))
{
foreach ($_POST['Events'] as $k => $event) {
$event_model[$k]->attributes = $_POST['Events'][$k];
}
}
// load events if Update...
if (isset($model->name) && (strlen($model->name))>0) {
$event_model[0]=Events::model()->findByAttributes(array('ancestor_id' => $model->id, 'type_string' => 'BIRT'));
$event_model[1]=Events::model()->findByAttributes(array('ancestor_id' => $model->id, 'type_string' => 'BAPT'));
$event_model[2]=Events::model()->findByAttributes(array('ancestor_id' => $model->id, 'type_string' => 'DEAT'));
}
foreach ($event_model as $k => $event) {
// which event?
switch ($k) {
case 0:
echo '<h2>Birth </h2> ';
break;
case 1:
echo '<h2>Baptism </h2> ';
break;
case 2:
echo '<h2>Death </h2> ';
break;
}
echo '
<div class="row">
'.$form->labelEx($event_model[$k],'['.$k.']place').'
'.$form->textField($event_model[$k],'['.$k.']place').'
'.$form->error($event_model[$k],'['.$k.']place').'
</div>
';
if ($k>0) {
/* no parish for BIRTH */
echo '
<div class="row">
'.$form->labelEx($event_model[$k],'['.$k.']parish_id').'
';
$parishes_list = CHtml::listData(Parishes::model()->findAll(array('order'=>'name ASC')), 'id', 'name');
$options = array(
'tabindex' => '0',
'empty' => 'select Parish',
);
echo '
'.$form->dropDownList($event_model[$k],'['.$k.']parish_id', $parishes_list, $options).'
'.$form->error($event_model[$k],'['.$k.']parish_id').'
</div>
';
}
echo '
<div class="row">
'.$form->labelEx($event_model[$k],'['.$k.']day').'
'.$form->textField($event_model[$k],'['.$k.']day').'
'.$form->error($event_model[$k],'['.$k.']day').'
</div>
<div class="row">
'.$form->labelEx($event_model[$k],'['.$k.']month').'
'.$form->textField($event_model[$k],'['.$k.']month').'
'.$form->error($event_model[$k],'['.$k.']month').'
</div>
<div class="row">
'.$form->labelEx($event_model[$k],'['.$k.']year').'
'.$form->textField($event_model[$k],'['.$k.']year').'
'.$form->error($event_model[$k],'['.$k.']year').'
</div>
';
}
?>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Thanks again!