Yii 1.1: Take more control of CGridview and model searching (related model or another controller)

6 followers

Suppose you have an Application in Yii that manages hotels each one has many customers.

So we should have the below tables with attributes

hotel (id,name) customer (id,surname) customer_to_hotel (id, hotel_id,customer_id)

Suppose now you want to have a page that displays the info of the hotel and all customers of the specific hotel. Also you want all the links (sorter columns), search fields and the pagination of the CGridview work with another controller/action (suppose you want to have distinct control for the view and search of the customer into the Hotel Controller for reusability or/and other reasons)

How to achieve that ?

This Article explain how to do that

HotelController.php (controller)

//this action manage both view of the hotel and view search customer
    public function actionViewHotel($hotel_id=null) {
 
        $customerToHotel = new CustomerToHotel('search');
        $customerToHotel->unsetAttributes();
 
        if (isset($_GET['customerToHotel']))
            $customerToHotel->attributes = $_GET['customerToHotel'];
 
       $hotel = Hotel::model()->findByPk($hotel_id);
            if ($hotel===null)
                throw new CHttpException(404, 'The requested page does not exist.');
 
        $this->render('viewHotel', array('hotel' => $hotel,'customerToHotel'=>$customerToHotel));
    }
 
    //this action can be used by ajax (directly from CGridview)
    public function actionSearchCustomer() {
 
        $customerToHotel = new CustomerToHotel('search');
        $customerToHotel->unsetAttributes();
 
        if (isset($_GET['customerToHotel']))
            $customerToHotel->attributes = $_GET['customerToHotel'];
 
        $this->renderPartial('_searchCustomersByHotel', array('customerToHotel' => $customerToHotel));
    }

customerToHotel.php (model)

//an extra search for specific hotel and other parameters
  public function searchByHotel($hotel_id, $routeUrl = null, $templateParams = array()) {
 
        $criteria = new CDbCriteria;
 
        $criteria->compare('id', $this->id);
        $criteria->compare('hotel_id', $hotel_id);
        $criteria->compare('customer_id', $this->customer_id);
 
        $item_count = self::model()->count($criteria);
 
        $pages = new CPagination($item_count);
        $pages->setPageSize(10);
 
        $sort = new CSort();
 
        if (!empty($templateParams)) {
            $pages->params = $templateParams;
            $sort->params = $templateParams;
        }
 
        if ($routeUrl) {
            $pages->route = $routeUrl;
            $sort->route = $routeUrl;
        }
 
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
            'pagination' => $pages,
            'sort' => $sort,
        ));
    }

_searchCustomersByHotel.php (view) //use a different action (or/and controller) and search method (only show customer filtered by specific hotel)

$this->widget('zii.widgets.grid.CGridView', array(
    'ajaxUrl' => $this->createUrl('searchCustomer', array('hotel_id' => $hotel->id)), // this takes care of the search using searchCustomer action and hodel id
    'dataProvider' => $customerToHotel->searchByHotel($hotel->id, 'searchCustomer', array('hotel_id' => $hotel->id)), //filter by hotel, routing to searchCustomer action, extra parameter of hotel id generated to the next request (like sort column links e.t.c)
    'filter' => $customerToHotel,
 
    'columns'=>array(
        'id',
        'hotel_id', //this should be the same for all rows (testing)
        'customer_id'
    ),
));

viewHotel.php (view) //display both hotel and customers in gridview

$this->widget('zii.widgets.CDetailView',
    'data'=>$hotel,
    'attributes'=>array(
        'id',
        'name',
    ),
));
 
$this->renderPartial('_searchCustomersByHotel' , array('customerToHotel'=>$customerToHotel));

Total 5 comments

#16667 report it
VincentM at 2014/03/17 11:30am
thanks

Thanks a lot, it seems to help me to understand a bit more about CGridView and some option of yii.

Anyway it works fine exept when I try to search, to switch page, to sort or any action on the CGrid I have an error 400, "NetworkError: 400 Bad Request" :s
(this when I try to switch to page 2 : "NetworkError: 400 Bad Request - http://localhost/LayoutColloques/index.php/admin/searchPersonne?Id_Evenements=45&ajax=yw1&page=2" )

I posted all my code here if you wanna try to help me : http://www.yiiframework.com/forum/index.php/topic/52488-how-to-have-a-grid-with-filtered-data/#entry242587

thx in advance and have a nice day :)

#15907 report it
KonApaz at 2013/12/28 09:19am
RE: Reference to other extension.

I agree with you

Both wiki and extensions are useful, each one for specific reasons.

P.S. Good extension :)

#15895 report it
le_top at 2013/12/27 11:02am
Reference to other extension.

Exactly, which is why I proposed a gentle look at the extension because extensions are also there to make life easier (and I hope that somebody with good explication skills for noobs will properly document the use of the extension ;-) ).

#15894 report it
KonApaz at 2013/12/27 10:07am
Re: RelatedSearchBehavior

Hi

Yes, there is extension(s) that uses same way, cetrainly

A wiki reveals and explains how it works instead an extension used directly.

So according to what users want either they read a wiki or use an extension

In any case thanks for your comment :)

#15887 report it
le_top at 2013/12/26 08:46pm
RelatedSearchBehavior

Hi Not exactly "the same", but look at my extension: Related Search Behavior and also at its Demo. All the columns of many related tables are fully searcheable. Imagine 'Album' is like the Hotel and 'Track' is like the customer', but you can also filter on many other columns from other tables. All made easy with Related Search Behavior.

Leave a comment

Please to leave your comment.

Write new article