It could be convenient to save different kind of models in the same view. This approach allows us to save time and to navigate from every single detail until a final item that merges all data is created. Handling different kind of models linked to each other it is not so different from what we have seen so far. The only point to take care of is the link (foreign keys) between models, which we must ensure is valid.
Therefore, the controller action will receive the $_POST
data encapsulated in the model's class name container; if we are thinking, for example, of the customer and reservation models, we will have two arrays in the $_POST
variable, $_POST['Customer']
and $_POST['Reservation']
, containing all the fields about the customer and reservation models.
Then all data must be saved together. It is advisable to use a database transaction while saving data because the action can be considered as ended only when all the data has been saved.
Using database transactions in Yii2 is incredibly simple! A database transaction starts with calling beginTransaction()
on the database connection object and finishes with calling the commit()
or rollback()
method on the database transaction object created by beginTransaction()
.
To start a transaction:
$dbTransaction = Yii::$app->db->beginTransaction();
Commit a transaction, to save all the database activities:
$dbTransaction->commit();
Rollback a transaction, to clear all the database activities:
$dbTransaction->rollback();
So, if a customer was saved and the reservation was not (for any possible reason), our data would be partial and incomplete. Using a database transaction, we will avoid this danger.
We now want to create both the customer and reservation models in the same view in a single step. In this way, we will have a box containing the customer model fields and a box with the reservation model fields in the view.
Create a view in basic/views/reservations/createCustomerAndReservation.php
, with the fields from the customer and reservation models:
<?php use yiihelpersHtml; use yiiwidgetsActiveForm; use yiihelpersArrayHelper; use appmodelsRoom; ?> <div class="room-form"> <?php $form = ActiveForm::begin(); ?> <div class="model"> <?php echo $form->errorSummary([$customer, $reservation]); ?> <h2>Customer</h2> <?= $form->field($customer, "name")->textInput() ?> <?= $form->field($customer, "surname")->textInput() ?> <?= $form->field($customer, "phone_number")->textInput() ?> <h2>Reservation</h2> <?= $form->field($reservation, "room_id")->dropDownList(ArrayHelper::map(Room::find()->all(), 'id', function($room, $defaultValue) { return sprintf('Room n.%d at floor %d', $room->room_number, $room->floor); })); ?> <?= $form->field($reservation, "price_per_day")->textInput() ?> <?= $form->field($reservation, "date_from")->textInput() ?> <?= $form->field($reservation, "date_to")->textInput() ?> </div> <div class="form-group"> <?= Html::submitButton('Save customer and room', ['class' => 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?> </div>
We have created two blocks in the form to fill out the fields for the customer and the reservation.
Now, create a new action named actionCreateCustomerAndReservation
in ReservationsController
in basic/controllers/ReservationsController.php
:
public function actionCreateCustomerAndReservation() { $customer = new appmodelsCustomer(); $reservation = new appmodelsReservation(); // It is useful to set fake customer_id to reservation model to avoid validation error (because customer_id is mandatory) $reservation->customer_id = 0; if( $customer->load(Yii::$app->request->post()) && $reservation->load(Yii::$app->request->post()) && $customer->validate() && $reservation->validate() ) { $dbTrans = Yii::$app->db->beginTransaction(); $customerSaved = $customer->save(); if($customerSaved) { $reservation->customer_id = $customer->id; $reservationSaved = $reservation->save(); if($reservationSaved) { $dbTrans->commit(); } else { $dbTrans->rollback(); } } else { $dbTrans->rollback(); } } return $this->render('createCustomerAndReservation', [ 'customer' => $customer, 'reservation' => $reservation ]); }
Ensure you pay attention to these two matters:
$reservation->customer_id = 0
: With this code, we avoid the validation error relating to the customer_id
requirement that appears when $reservation
is validatedBrowse to http://hostname/basic/web/reservations/create-customer-and-reservation
to see the complete page:
3.147.78.174