As mentioned in the previous paragraph, the columns
property of the GridView widget is mainly filled with strings.
When we need to apply a specific format, such as currency or date/time, we can append this specification to the column name with a colon and the type used for formatting, as currency
or datetime
.
But the most general form of a GridView column is an object of the yiigridColumn
class, derived by the yiigridDataColumn
class.
A GridView column extended by the yiigridColumn
class is rendered using an array with the following keys:
[ // can be omitted, as it is the default 'class' => 'yiigridDataColumn', 'attribute', // name of model attribute 'format', // format use to display data 'header', // header of column 'footer', // footer of column 'visible', // flag to set visibility 'content' // callback to print data ],
There are also other parameters but these ones are the most used.
We are now ready to create a customer grid that contains a reference to the linked reservation list in every row. First of all, make sure that the structure and the data for the customer and reservation tables is the following:
-- -- Structure of Table `customer` -- CREATE TABLE IF NOT EXISTS `customer` ( `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, `name` varchar(50) NOT NULL, `surname` varchar(50) NOT NULL, `phone_number` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ); -- -- Data Dump of Table `customer` -- INSERT INTO `customer` (`id`, `name`, `surname`, `phone_number`) VALUES (1, 'James', 'Foo', '+39-12345678'), (2, 'Bar', 'Johnson', '+47-98438923'); -- -- Structure of Table `reservation` -- CREATE TABLE IF NOT EXISTS `reservation` ( `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, `room_id` int(11) NOT NULL, `customer_id` int(11) NOT NULL, `price_per_day` decimal(20,2) NOT NULL, `date_from` date NOT NULL, `date_to` date NOT NULL, `reservation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `room_id` (`room_id`), KEY `customer_id` (`customer_id`) ); -- -- Data Dump of table `reservation` -- INSERT INTO `reservation` (`id`, `room_id`, `customer_id`, `price_per_day`, `date_from`, `date_to`, `reservation_date`) VALUES (1, 2, 1, 90.00, '2015-04-01', '2015-05-06', '2015-05-24 22:45:37'), (2, 2, 1, 48.00, '2019-08-27', '2019-08-31', '2015-05-24 22:45:37'), (3, 1, 2, 105.00, '2015-09-24', '2015-10-06', '2015-06-03 00:21:14');
Create a new controller named CustomersController
in basic/controllers/CustomersController.php
with the actionGrid
action to display a list in the grid view:
<?php namespace appcontrollers; use Yii; use yiiwebController; use appmodelsCustomer; use yiidataActiveDataProvider; class CustomersController extends Controller { public function actionGrid() { $query = Customer::find(); $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => [ 'pageSize' => 10, ], ]); return $this->render('grid', [ 'dataProvider' => $dataProvider ]); } }
This action actionGrid
simply creates a data provider with all the data from the customer (unfiltered) and with a pagination that displays ten items on a page. Finally, render the grid view.
This is the content of the grid view in basic/views/customers/grid.php
:
<?php use yiigridGridView; use yiihelpersHtml; ?> <h2>Customers</h2> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ 'id', 'name', 'surname', 'phone_number', [ 'header' => 'Reservations', 'content' => function ($model, $key, $index, $column) { return Html::a('Reservations', ['reservations/grid', 'Reservation[customer_id]' => $model->id]); } ], [ 'class' => 'yiigridActionColumn', 'template' => '{delete}', 'header' => 'Actions', ], ], ]) ?>
The last two columns require particular explanation.
The penultimate one, Reservation
, displays a link to give you access to the list of all customer reservations. We have put Reservations
as the header and filled the content
property with dynamic data passed from the callback function, which returns an HTML link to the reservations/index
route with a parameter indicating customer_id
selected.
The last column headed Actions
displays the ActionColumn with the single action delete
to remove the selected record.
Point your browser to http://hostname/basic/customers/grid
and you should have the following output:
We can complete this example by just putting a counter near the Reservations
link to indicate the number of reservations for each customer.
For this purpose, we need to add a new relation named getReservationsCount
to the Customer model in basic/models/Customer.php
, which returns the number of reservations linked to the customer:
public function getReservationsCount() { return $this->hasMany(appmodelsReservation::className(), ['customer_id' => 'id'])->count(); }
Now we can modify the penultimate column with:
[ 'header' => 'Reservations', 'content' => function ($model, $key, $index, $column) { $title = sprintf('Reservations (%d)', $model->reservationsCount); return Html::a($title, ['reservations/grid', 'Reservation[customer_id]' => $model->id]); } ],
If we refresh our browser now, we will see near the Reservations
anchor link, the correct number of reservations for that customer appears.
This example represents the complete reservations list displayed when a user clicks on the link Reservations
.
Create ReservationsController
as a new file in basic/controllers/ReservationsController.php
with an action grid
and the following content:
<?php namespace appcontrollers; use Yii; use yiiwebController; use appmodelsReservation; use yiidataActiveDataProvider; class ReservationsController extends Controller { public function actionGrid() { $query = Reservation::find(); if(isset($_GET['Reservation'])) { $query->andFilterWhere([ 'customer_id' => isset($_GET['Reservation']['customer_id'])?$_GET['Reservation']['customer_id']:null, ]); } $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => [ 'pageSize' => 10, ], ]); return $this->render('grid', [ 'dataProvider' => $dataProvider ]); } }
In this controller, we applied an andFilterWhere
condition to query whether $_GET['Reservation']
is set. The andFilterWhere()
method will apply a filter passed as a parameter only if the condition is not empty. So if $_GET['Reservation']['customer_id']
is not set, the andFilterWhere()
condition parameter will have a null value and will not be appended to any other query condition.
3.143.244.83