i am newbii in yii development and have an issue while displaying data using cgridview as it is showing only first record
Motel,Hotel,Roomcategory and halls are models in which PK and FK are passing ...
Code is here
$sponsorm = Motel::model()->find('MotelId=:MotelId', array(':MotelId'=>Yii::app()->user->id));
$sponsorhotel = Hotel::model()->find('hotelId=:hotelId', array(':hotelId'=>$sponsorm->MotelId));
$room = Roomcategory::model()->find('hotelId=:hotelId', array(':hotelId'=>$sponsorhotel->hotelId));
$halls = Halls::model()->find('hotelId=:hotelId', array(':hotelId'=>$sponsorhotel->hotelId));
echo CHtml::image(Yii::app()->request->baseUrl.'/img/4.png');
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'businessowner-grid',
'dataProvider'=>$room->search(),
//'filter'=>$sponsore,
'columns'=>array(
'roomCategoryNames',
'noOfRooms',
'price',
),
));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'businessowner-grid',
'dataProvider'=>$halls->search(),
//'filter'=>$sponsore,
'columns'=>array(
'Type',
//'noOfHalls',
'seats',
'price',
),
));
Right now you are finding only one record because you use find to get one specific record. So you assign this record data to model variables and then you do
$model->search();
This searches from specific table multiple values but you have set the attributes so, that it matches only one record.
To get Motel gridview data use following code:
$sponsorm = $dataProvider=new CActiveDataProvider('Motel', array(
'criteria'=>array(
'condition'=>'MotelId = :MotelId',
'params' => array(':MotelId'=>Yii::app()->user->id)
),
));
It is doing the same as search() but the difference is that searching criteria is different. You can use also code below.
$motelModel = new Model();
$motelModel->MotelId = Yii::app()->user->id;
Now there is only one attribute assigned an is setting a criteria to match all rows what has this user id in MotelId field.
$modelModel->search();
Also, I see that you echo something between logic. Please do not do that. Output data only in views and keep the logic out of views. :)
Related
I have two tables: user and asset and there is user_asset table that makes many_many relation
Now I want to show only the assets related with logged-in user in CGridView (user_id comes from Yii::app()->user->id)
How to write a criteria that makes it possible?
1) You need to define your relations in both of the model
user:
'assets' => array(self::MANY_MANY, 'Asset', 'user_asset(user_id, asset_id)'),
asset:
'users' => array(self::MANY_MANY, 'Asset', 'user_asset(asset_id, user_id)'),
2) You Create a dataProvider that will fetch only the recquired datas (define it in a model (best) or a controller bu not in a view):
$dataProvider=new CActiveDataProvider('Asset', array(
'criteria'=>array(
'with'=>array(
'users'=>array(
'condition' => 'id = ' . Yii::app()->user->id
),
),
),
...
));
3) You give to your CGridView the good provider:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
...
));
The code is given as example, you should adapt it to your need!
I got it work, adding this inside the Model class's search method:
$criteria->with=array(
'users'
);
$criteria->together = true;
$criteria->condition = "users_users.user_id='".Yii::app()->user->id."'";
... and inside CActiveDataProvider declaration:
'criteria'=>array(
'with' => 'users',
'together'=>true,
'condition'=>'users_users.user_id = '.Yii::app()->user->id,
),
Maybe not the best way but does what needed. users_users is sql table alias by Yii, I got a hint from error message :)
I am trying to use drop down list widget :
$this->widget('ext.multiselect.JMultiSelect',array(
'model'=>$model,
'attribute'=>'attribute',
'data'=>$data,
// additional javascript options for the MultiSelect plugin
'options'=>array()
));
What I want to know is that Details of each option available in the widget array Like what is 'attribute' , 'model' and'data' represent , as I an unable to understand it form the documentation.
The model param is the model you are creating the multi select for.
The attribute is the model attribute you are creating the multi select for.
The data is an array of key/value pairs for the list items you want to display in the multi select.
For example, if you had a model 'User' and in that model you had a field 'access_rights' and you wanted to have that field as a multi select box with a few values, you might do something like:
In your controller:
$model = new User;
$data = array(
'admin_area'=>'Admin Area Access',
'product_area'=>'Product Area Access',
'customer_area'=>'Customer Area Access',
... etc
);
In your form in your view file:
$this->widget('ext.multiselect.JMultiSelect',array(
'model'=>$model,
'attribute'=>'access_rights',
'data'=>$data,
// additional javascript options for the MultiSelect plugin
'options'=>array()
));
Edit:
To add data to the multi select options from another model you can use the CHtml::listData() method, this takes an active record result set and converts it into an array of key/value pairs so you can use in any of the other CHtml methods that require a key/value pair. To do this you simply get the records you're after from the database using active record, eg;
$myData = Data::model->findAll();
You can then put that into the listData() method and it'll create your array:
$this->widget('ext.multiselect.JMultiSelect',array(
'model'=>$model,
'attribute'=>'access_rights',
'data'=>CHtml::listData($myData, 'id', 'name'),
// additional javascript options for the MultiSelect plugin
'options'=>array()
));
(where 'id' and 'name' are the fields from the model table that you want to be the 'key' and 'value' within the array)
echo $form->dropDownList($model, 'category', CHtml::listData(TblCategory::model()->findAll(),
'id', 'category_name'), array('empty' => '---Select Category---',
'style' => 'width:350px;')), array() ?>
<?php echo $form->error($model, 'category'); ?>
I have the following example code:
$dataProvider = new CActiveDataProvider('firstTable',
array('criteria' => array(
'select' => 't.firstfield,secondTable.secondfield',
'join' => 'join secondTable on secondTable.id=t.secondTable_id',
),
'pagination' => array(
'pageSize' => 10,
),
));
$results=$dataProvider->getData();
After running the code above, firstField (from the model table - firstTable) is available in the object, but secondField (from the joined table - secondTable) is not.
Can anyone provide assistance on what is wrong with the code or why the "select" option is not picking up the secondField?
it would be better if you use CDbCriteria, that has a better solution to join table with the help of relations. I can show the example with CDbCriteria.
$criteria = new CDbCriteria;
$criteria->select = 'firstfield';
$criteria->with = array('secondTable_relation'=>array('select'=>'secondfield'));
$dataProvider = new CActiveDataProvider('firstTable',
array('criteria' => $criteria,
'pagination' => array(
'pageSize' => 10,
),
));
$results=$dataProvider->getData();
secondTable_relation is a relation name with secondTable.
Can anyone provide assistance on what is wrong with the code or why the "select" option is not picking up the secondField?
Answer:
That is happening because you have not selected the field which relates the two tables, i.e the foreign key in firstTable : secondTable_id. So if you do:
'select' => 't.firstfield,t.secondTable_id,secondTable.secondfield',
you will be able to access the secondField of secondTable:
$singleresultrow->secondTableRelationName['secondField'];// a single result row can be obtained by foreach iteration over $results
However there will still be another query (Lazy Loading) when you access the secondField. And the initial(before lazy) object returned will not have the secondTable object filled.
The problem i think lies in the fact that by default yii accesses the related fields by lazy loading, and for that to happen the related foreign_key should be present in the model you are trying to make a dataprovider of, here it is firstTable, and the foreign_key secondTable_id.
I am using CGridView in Yii, how can I display a single record in 2 lines?
Basically I want to show a record details in 1st row of table and on other row I want to display its summary, I tried it with div and css but can't get proper results, is anyone there who can help me in this case?
I am using like this:
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'bidding-grid',
'itemsCssClass' => 'data-default',
'dataProvider'=>$model,
'summaryText' => '',
'columns'=>array(
'people_detail_for_bid.Person' => array(
'type'=>'raw',
'name'=>'people_detail_for_bid.Person',
'value'=>'Yii::app()->Controller->createUserNameLink($data->people_detail_for_bid->PeopleFirstName." ".$data->people_detail_for_bid->PeopleLastName, $data->people_detail_for_bid->PeopleId).
"<br><span class=decriptionText>".$data->people_detail_for_bid->PeopleDesignation."</span>".
"<br><span class=decriptionText>".$data->people_detail_for_bid->PeopleEmail."</span>"',
'htmlOptions'=>array('width'=>200),
),
'timeAgo' => array(
'type'=>'raw',
'name'=>'timeAgo',
'value'=>'"<span class=decriptionText>".Yii::app()->Controller->_ago($data->PBPostedOn)."</sapn>"',
'htmlOptions'=>array('width'=>150),
),
),
));
?>
I think the best and cleanest way to accomplish this is to create a new extension and extend it to CGridView, override the renderTableRow function like this:
/**
* Renders a table body row.
* #param integer $row the row number (zero-based).
*/
public function renderTableRow($row)
{
if($this->rowCssClassExpression!==null)
{
$data=$this->dataProvider->data[$row];
echo '<tr class="'.$this->evaluateExpression($this->rowCssClassExpression,array('row'=>$row,'data'=>$data)).'">';
}
else if(is_array($this->rowCssClass) && ($n=count($this->rowCssClass))>0)
echo '<tr class="'.$this->rowCssClass[$row%$n].'">';
else
echo '<tr>';
$colCtr = 0;
foreach($this->columns as $column){
$column->renderDataCell($row);
$colCtr++;
}
echo "</tr>\n";
echo "<tr><td colspan=\"$colCtr\">This is the summary row. </td></tr>";
}
You can customize what you are rendering in the columns, so if you want to show two different fields of your table in the same row, you have to create a function in your model:
public function customColumn()
{
return $this->PeopleDesignation.'<br/>'.$this->PeopleEmail;
}
And then assign the method to the value of your column:
array(
'type'=>'html',
'value'=>'$data->customColumn()'
),
Cheers, Pablo.
After too much search .. and I tried with different ways now finally got a solution for this .. that solution is basically a kind of 2nd way to do anything not actual way .. but it works to me ..
.....
.....
'timeAgo' => array(
'type'=>'raw',
'name'=>'timeAgo',
'value'=>'"<span class=decriptionText>".Yii::app()->Controller->_ago($data->PBPostedOn)."</sapn></td></tr><tr><td colspan=\"6\"><span class=decriptionText>".$data->PBSummary."</span>"',
'htmlOptions'=>array('width'=>150),
),
.....
.....
added some table tags on last column to close row and added another one.
hope it works for all ..
thanks ..
Sounds like 2 interleaved CGridViews. So you might try that, but I can't imagine it will work out well:
Overlay one CGridView over the other, with enough transparent space in each row for the other to display it's row, and ...
a. one `CGridView` table offset vertically by half a row height, *OR*
b. one table's row's text vertically top-aligned & the other bottom-aligned
But somehow I doubt that's a CGridView capability ;) And keeping the two in sync so they pagenate and scroll together would be darn near impossible. Sounds like you need to enhance CGridView or derive a new widget from CGridView. I wonder if JQuery has something to do this?
I have two tables tbl_business and business_contacts of the following structure:
tbl_business
---
business_id (PK)
othercolumns
and
business_contacts
---
contact_id (PK)
business_id
othercolumns
The scenario is that one business row has many contacts. I am using cGridview using gii's CRUD generator and needed to display firstname and lastname from business_contacts (one of multiple possible rows in the table) for each tbl_business record.
As far as I understand, I've updated the relation function in tbl_business's model as:
'businesscontacts' => array(self::HAS_MANY,'BusinessContact','business_id','select' => 'contact_firstname, contact_lastname')
and for the same, a contact relation is defined in the business_contacts' model as:
'contactbusiness' => array(self::BELONGS_TO,'BusinessContact','business_id')
I expected that would work for pulling related records so that I can have something in the grid like, business_id, contact_firstname, contact_lastname , ... otherbusinesstablecolumns .. but I'm only getting blank values under firstname and lastname .. could someone please help me understand the error? :(
So you are trying to display a table of Businesses (tbl_business) using CGridView? And in each Business's row you want to list multiple Contacts (business_contacts)?
CGridView does not support displaying HAS_MANY relations by default. CGridView makes it easy to list which Business a Contact BELONGS_TO (i.e. you can use a column name like contactbusiness.business_id), but not all of the Contacts that are in a business.
You can do it yourself though, by customizing a CDataColumn. (Note: this will not allow you to sort and filter the column, just view. You'll have to do a lot more work in to get those working.)
First, in your Business model, add a method like this to print out all of the contacts:
public function contactsToString() {
$return = '';
foreach ($this->businesscontacts as $contact) {
$return .= $contact->contact_firstname.' '.$contact->contact_firstname.'<br />';
}
return $return;
}
(EDIT: Or do this to print out just the first contact):
public function contactsToString() {
if($firstContact = array_shift($this->businesscontacts)) {
return $firstContact->contact_firstname.' '.$firstContact->contact_firstname;
}
return '';
}
Then make a new column in your grid and fill it with this data like so:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'business-grid',
'dataProvider'=>$model->yourDataProviderFunction(),
'columns'=>
'business_id',
array(
'header'=>'Business Contacts', // give new column a header
'type'=>'HTML', // set it to manual HTML
'value'=>'$data->contactsToString()' // here is where you call the new function
),
// other columns
)); ?>
EDIT2: Yet another way of doing this, if you just want to print out ONE of a HAS_MANY relation, would be to set up a new (additional) HAS_ONE relation for the same table:
public function relations()
{
return array(
'businesscontacts' => array(self::HAS_MANY,'BusinessContact','business_id','select' => 'contact_firstname, contact_lastname') // original
'firstBusinesscontact' => array(self::HAS_ONE, 'BusinessContact', 'business_id'), // the new relation
);
}
Then, in your CGridView you can just set up a column like so:
'columns'=>array(
'firstBusinesscontact.contact_firstname',
),
Getting only the first contact could be achieved like this also:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'business-grid',
'dataProvider'=>$model->yourDataProviderFunction(),
'columns'=>
'business_id',
//....
array(
'name' => 'contacts.contact_firstname',
'value' => '$data->contacts[0]->contact_firstname', // <------------------------
'type' => 'raw'
);
//....
),