Handling related models in YII forms


Many AWBs can be carried in one Trip. One AWB can be carried across Many Trips. We will use MySQL for the database. Below is the schema. tbl_tripAWB is the junction table.

CREATE TABLE tbl_trip(

id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,

truckId TINYINT UNSIGNED NOT NULL,

departureDate DATETIME NOT NULL,

tripOrigin MEDIUMINT UNSIGNED NOT NULL,

tripDestination MEDIUMINT UNSIGNED NOT NULL,

arrivalDate DATETIME NOT NULL,

tripFor BOOLEAN NOT NULL DEFAULT 0,

tripStatus VARCHAR(125),

trip TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,

INDEX (truckId),

INDEX (tripOrigin),

INDEX (tripDestination)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE tbl_awb(

id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,

awbPrefix VARCHAR(3) NOT NULL,

awbNumber VARCHAR(8) NOT NULL,

awbAirport MEDIUMINT UNSIGNED NOT NULL,

awbCarrier TINYINT UNSIGNED NOT NULL,

awbPieces TINYINT UNSIGNED NOT NULL,

awbWeight MEDIUMINT UNSIGNED NOT NULL,

awb TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,

INDEX (awbAirport),

INDEX (awbCarrier)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE tbl_tripAwb(

id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,

trip INTEGER UNSIGNED NOT NULL,

awb INTEGER UNSIGNED NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE tbl_tripAwb

ADD CONSTRAINT FOREIGN KEY (trip) REFERENCES tbl_trip (id) ON UPDATE CASCADE,

ADD CONSTRAINT FOREIGN KEY (awb) REFERENCES tbl_awb (id) ON UPDATE CASCADE;

Update Trip form to display the list box with multi select containing AWBs.

labelEx($model,’tripAwbs’); ?>
dropDownList($model, ‘tripAwbs’, CHtml::listData(Awb::model()->findAll(), ‘id’, ‘awbNumber’, ‘awbPrefix’),array(‘multiple’=>’multiple’, ‘size’=>5)
); ?>
error($model,’tripAwbs’); ?>

Yii automatically created the below relationship


'tripAwbs' => array(self::HAS_MANY, 'TripAwb', 'trip'),

In order for the creation of a new Trip to work, you’ll need to update the Controller to handle the tripAwbs. Within the actionCreate() method (of TripController), after the Trip has been saved, loop through each AWB and add that record to tbl_tripAwb. The beginning of actionCreate() would look like:

if(isset($_POST['Trip']))
{
$model->attributes=$_POST['Trip'];
if($model->save()) {
foreach ($_POST['Trip']['tripAwbs'] as $awb) {
$tripAwb = new TripAwb;
$tripAwb->trip = $model->id;
$tripAwb->awb = $awb;
if (!$tripAwb->save()) print_r($tripAwb->errors);
// $this->redirect(array('view','id'=>$model->id));
}}
}

The form has already been created and populated, but to get it to indicate existing selections, we need to pass along the tbl_tripAwb values. You might think that you can just fetch all the tbl_tripAwb records where id equals the Model’s id (in other words, perform a with(‘tripAwb’)-> retrieval), but you can’t. For the drop-down menu in the form to preselect the right values, the form needs to access an array of values, not an array of objects. To achieve that, add some code to the loadModel() method of the TripController. This method is called for the update, delete, and view actions and just returns a single Model. The Model is loaded using:


public function loadModel($id)
{

$model=Trip::model()->findByPk($id);

// added for update by karthick
$criteria=new CDbCriteria;
$criteria->condition=’trip=:trip’;
$criteria->select = ‘awb’;
$criteria->params=array(‘:trip’=>$_GET[‘id’]);
$tripAwbs = TripAwb::model()->findAll($criteria);

$Awbs = array();
foreach ($tripAwbs as $awb) {
$Awbs[] = $awb->awb;
}

$model->tripAwbs = $Awbs;

if($model===null)
throw new CHttpException(404,’The requested page does not exist.’);
return $model;
}

Then update the tbl_tripAwb when the form is submitted (and the post is updated). The easiest way to handle all possibilities is to clear out the existing values (for this trip) in tbl_tripAWb, and then add them new. To do that, in actionUpdate() of the TripController, you would have:


if(isset($_POST['Trip']))
{
$model->attributes=$_POST['Trip'];
if($model->save()) {
$criteria=new CDbCriteria;
$criteria->condition='trip=:trip';
$criteria->params=array(':trip'=>$model->id);
tripAwb::model()->deleteAll($criteria);

// repeat of for each loop found in actionCreate()

foreach ($_POST[‘Trip’][‘tripAwbs’] as $awb) {
$tripAwb = new TripAwb;
$tripAwb->trip = $model->id;
$tripAwb->awb = $awb;
if (!$tripAwb->save()) print_r($tripAwb->errors);
}

$this->redirect(array(‘view’,’id’=>$model->id));
}

}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s