I have a requirement where I would like to display a list of records and the information from each record can come from a umber of tables. To further explain I have the following tables:
Table srp with columns id (PK), srpname, idbusiness (FK), idsite (FK)
Table business with columns id (PK), businessname
Table site with columns id (PK), sitename
Table srpprimary with columns id (PK), idsrp (FK), pname
Table srpdepname with columns id (PK), idsrp (FK), dname
An srp can have multiple entries in the table srpprimary and one entry in each of the other tables business, site, srpdepname
What I would like is to display an srp record along with all the pname entries in the table srpprimary, the dname from the table srpdepname and the actual business name and site name.
I looked at the CListView but could not see how I could get this additional data.
Any suggestions on how the above could best be achieved would be greatly appreciated.
Kind regards
e25taki
To help you in this question and in your next project I recommended you to use database relations :
1- prraper your datbase
2- write your relations on paper bettwen tables
3- do it (use phpmyadmin for example ):
by GUI methode
How to create a relation between two tables using PHPMyAdmin?
https://www.youtube.com/watch?v=IdQGFZwP7Xc
Sql method
ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
4- now you can use yii gii to create your code and all you relations will be save in model class
5- load data in view will be so so easy now :
For Example if your model is like :
<?php
..
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'co' => array(self::BELONGS_TO, 'Country', 'co_id'),
'events' => array(self::HAS_MANY, 'Events', 'city'),
'news' => array(self::HAS_MANY, 'News', 'city'), /// here
'users' => array(self::HAS_MANY, 'Users', 'city'),
);
}
...
?>
So we can access to all news table that related to current city by call it as :
echo $model->news->title;
It's all about the relations in your models.
With correct relations, you can access data like:
$srp = Srp::model()->findByPk(1);
$sites = $srp->sites; // gets an active record-array with a HAS_MANY-relation
$site = $srp->site; // gets the active record directly with a HAS_ONE-relation
Considering the code generation in Gii, you'll have a much easier time if you rename your foreign keys so they end with "id" or "_id". That way, you'll get sensiblle relations automatically when you generate your models. (Though they still might need to be tweaked a bit to suit your needs.)
With your new relations, you can create a listview like this in your view:
$dataProvider=new CActiveDataProvider('Srp');
$this->widget('zii.widgets.CListView', array(
'dataProvider' => $dataProvider,
'itemView' => '_view',
));
And access your data something like this (_view.php) :
<b>Id:</b> // Or better yet: echo CHtml::encode($data->getAttributeLabel('id'));
<?php echo $data->id; ?>
<br />
<b>Business:</b>
<?php echo $data->business->name; ?>
<br />
<b>Site:</b>
<?php echo $data->site->name; ?>
<br />
<b>Depname:</b>
<?php foreach ($data->srpdepnames as $dep): ?>
<?php echo $dep->dname; ?>,
<?php endforeach ?>
<br />
<b>Depname:</b>
<b><?php echo CHtml::encode($data->getAttributeLabel('srpprimary_id')); ?>:</b>
<?php foreach ($data->srpprimaries as $prime ){
echo CHtml::link( // If you want links instead of just text.
CHtml::encode($prime->pname),
array('SrpPrimary/View', 'id'=>$prime->id)
);
}?>
(I haven't tried this, so it's not a working example. Sorry! But it should give you an idea and it's not far from the truth. )
In controller.php
public function actionQueries()
{
$dataProvider=new CActiveDataProvider('Student', array(
'criteria' => array(
'with' =>'student',
'join' => 'INNER JOIN studentinfo si ON si.stud_id=t.id',
)
));
$this->render('query',array(
'dataProvider'=> $dataProvider,
));
}
in a view,in tables model view make php file for ex query.php
<?php
/* #var $this StudentController */
/* #var $model Student */
$this->breadcrumbs=array(
'Students'=>array('query'),
//$user->name,
);
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view', // refers to the partial view named '_post'
'enablePagination'=>true,
'sortableAttributes'=>array(
'name',
)
));
?>
// add your new feilds in _view.php file:
// in controller.php
in accsessRule() add your new file for authentication for ex.queris
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view','queries'),
'users'=>array('*'),
),
}
Related
I have a table name business and a table name review business. In business table, i just have business name, business image and business information. In review business table i have business_id as foreign key, user_id as foreign key and rate(int) five star and review field. Now i am as an admin can give review easily, by selecting a particular user from the drop down list, by choosing a particular business from a drop down list and then give rate and review. I am using dzraty extension. It is working fine. Also i am showing reviews given by admin, on the business page.My question is what if a user, wants to give a review on the business page? for that he needs the five star rating field and review field which is present in review business table, view "form". I want to show rating and review fields on the business page, so that user can write a review and post it. This functionality is working in review business view, i just want it in another view.
For understanding i am posting models data.
Buisness model
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'addresses' => array(self::HAS_MANY, 'Address', 'business_id'),
'businessItems' => array(self::HAS_MANY, 'BusinessItems', 'business_id'),
'businessPackages' => array(self::HAS_MANY, 'BusinessPackage', 'business_id'),
'facilities' => array(self::HAS_MANY, 'Facilities', 'business_id'),
'reviewBusinesses' => array(self::HAS_MANY, 'ReviewBusiness', 'business_id'),
'subCategoryBusinesses' => array(self::HAS_MANY, 'SubCategoryBusiness', 'business_id'),
);
}
Review business model
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'business' => array(self::BELONGS_TO, 'Business', 'business_id'),
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
'profile' => array(self::BELONGS_TO, 'Profiles', 'id','through'=>'user'),
);
}
form.php of review business
<?php
/* #var $this ReviewBusinessController */
/* #var $model ReviewBusiness */
/* #var $form BSActiveForm */
?>
<?php $form=$this->beginWidget('bootstrap.widgets.BsActiveForm', array(
'id'=>'review-business-form',
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation'=>false,
)); ?>
<p class="help-block">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<?php echo $form->labelEx($model,'user_id'); ?>
<?php
$this->widget('ext.select2.ESelect2',array(
'name'=>'ReviewBusiness[user_id]',
'data'=>CHtml::listData(User::model()->findAll(), 'id', 'username'), //the whole available list
'htmlOptions'=>array(
'placeholder'=>' search User name?',
//'options'=>$options, //the selected values
//'multiple'=>'multiple',
'style'=>'width:530px',
),
));
?>
<?php //echo $form->textFieldControlGroup($model,'business_id'); ?>
<div class="gap-small"></div>
<?php echo $form->labelEx($model,'Business_name'); ?>
<?php
$this->widget('ext.select2.ESelect2',array(
'name'=>'ReviewBusiness[business_id]',
'data'=>CHtml::listData(Business::model()->findAll(), 'id', 'business_name'), //the whole available list
'htmlOptions'=>array(
'placeholder'=>' search Business name?',
//'options'=>$options, //the selected values
//'multiple'=>'multiple',
'style'=>'width:530px',
),
));
?>
<div class="gap-small"></div>
<div class="ratings"> <!--use class in order to show rating horizontally -->
<?php
$this->widget('ext.DzRaty.DzRaty', array(
'model' => $model,
'attribute' => 'rating',
)); ?>
</div>
<?php echo $form->textarea($model,'review',array('maxlength'=>500)); ?>
</br>
<?php echo BsHtml::submitButton('Submit', array('color' => BsHtml::BUTTON_COLOR_PRIMARY)); ?>
<?php $this->endWidget(); ?>
I want to display the name of Shift instead of shift_id
I have a dropboxlist from other table that is like this
<div>
<?php echo $form->labelEx($model,'mon'); ?>
<?php echo $form->dropDownList($model, 'mon', CHtml::listData(
Shift::model()->findAll(), 'shft_id', 'name'),
array('prompt' => 'Select a Department')
); ?>
<?php echo $form->error($model,'mon'); ?>
I have two tables that is
Day: id_day,mon,tues,wed,etc
Shift: shft_id,start,end,name,status
Here is the relation in the day
'shift'=>array(self::HAS_MANY,'Shift','shft_id'),
For Shift:
'day'=>array(self::BELONGS_TO,'Day','id_day'),
It is already working. The choices in the dropbox was the name of the Shift, and puts the shft_id in the mon,tues,wed,etc. In the view of the form it looks like
id_user: 3
mon:5
tues:5
wed:6
what I wanted to be is that in the view.
id_user: 3
mon: 6am-5pm
tues: 7am-6pm
etc.etc.
I dont know what command it is. I have no idea. Help me please
Instead of User::getusername() method.
I think you can simply use this in one line.
// format models resulting using listData
<?php echo $form->dropdownlist($model,'user_id', CHtml::listData(User::model()->findAll(),'id', 'name')); ?>
below is an example which I think may solved your problem
in _form.php
<?php echo $form->dropdownlist($model,'user_id', User::getusername()); ?>
<?php echo $form->error($model,'user_id'); ?></th>
in User model
public function getusername()
{
$criteria2=new CDbCriteria;
$criteria2->select='*';
$quser=User::model()->findAll($criteria2);
foreach($quser as $r)
{
$user_id= $r->user_id;
$user_name=$r->user_name;
$user_array[$user_id]=$user_name;
}
return $user_array;
}
I'm trying to understand what you are really asking. I believe you were saying that you are already able to populate your records correctly from the dropdowns. But when you are displaying, the view is only showing the shift_id value? The relation for the day should be able to get your shift name. How are you displaying the list:
mon: 5
tue: 5
wed: 6
I'm trying to understand if you need help displaying the dropdown items properly, or how to display the shift name later after the values have been set in the database. Also, your 'Day' table has me confused. What are the field names? Are they 'day_id' and 'day'? Or do you actually name the fields after each day of the week?
If you are displaying the data through a foreach and are getting each day (let's assume it is $day) object, then the relationship to 'shift' can give you the name like this: echo $day->shift->name; if the name displays as '#am-#pm'. Otherwise you can display it like this:
echo sprintf('%d a.m. - %d p.m.',$day->shift->start,$day->shift->end);
Thanks for the people who helped me. It did lead me to the answer anyone who has the same problem here is what i did.
In my model/Day
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'monday'=>array(self::BELONGS_TO,'Shift','mon'),
'tuesday'=>array(self::BELONGS_TO,'Shift','tue'),
'wednesday'=>array(self::BELONGS_TO,'Shift','wed'),
'thursday'=>array(self::BELONGS_TO,'Shift','thurs'),
'friday'=>array(self::BELONGS_TO,'Shift','fri'),
'saturday'=>array(self::BELONGS_TO,'Shift','sat'),
'sunday'=>array(self::BELONGS_TO,'Shift','sun'),
);
}
and In my models/Shift
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'day_mon' =>array(self::HAS_MANY,'Day','mon'),
'day_tue' =>array(self::HAS_MANY,'Day','tue'),
'day_wed' =>array(self::HAS_MANY,'Day','wed'),
'day_thurs'=> array(self::HAS_MANY,'Day','thurs'),
'day_fri'=>array(self::HAS_MANY,'Day','fri'),
'day_sat'=>array(self::HAS_MANY,'Day','sat'),
'day_sun'=>array(self::HAS_MANY,'Day','sun'),
);
}
The problem is with my relations. its not set properly, so you need to set it properly then go to Day/view
<?php $this->widget('bootstrap.widgets.TbDetailView',array(
'data'=>$model,
'attributes'=>array(
'id_day',
array(
'name'=>'mon',
'value'=>CHtml::encode($model->monday->name)
),
Here is the output
If you have a detail veiw then use the following code:
widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'name',
array(
'label' => $model->shift->getAttributeLabel('shift_name'),
'value' => $model->shift->shift_name
),)); ?>
In case anybody else will be in my boat, what you will need to do is edit view.php in view/modelname/view.php
widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'name',
'country_id')); ?>
into
widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'name',
array(
'label' => $model->country->getAttributeLabel('country'),
'value' => $model->country->name
),)); ?>
I want to display country name instead of country id in user profile view( country id is FK in user profile tbl) .
anyone can help me with this ?
This is my view controller/action in which I have Country model as well:
public function actionView($id)
{
$model = new TblUserProfile;
$model = TblUserProfile::model()->find('user_id=:user_id', array(':user_id' => $id));
$countrymodel = new Country;
$countrymodel = Country::model()->findAll();
// var_dump($countrymodel->name);
// die();
$this->render('view', array(
'model' => $model ,
'country' =>$countrymodel
));
}
This is my view
<div class="view">
<b><?php echo CHtml::encode($data->getAttributeLabel('id')); ?>:</b>
<?php echo CHtml::link(CHtml::encode($data->id), array('view', 'id'=>$data->id)); ?>
<br />
<b><?php echo CHtml::encode($data->getAttributeLabel('user_id')); ?>:</b>
<?php echo CHtml::encode($data->user_id); ?>
<br />
<b><?php echo CHtml::encode($data->getAttributeLabel('user_occuption')); ?>:</b>
<?php echo CHtml::encode($data->user_occuption); ?>
<br />
<b><?php
// $model = TblUserProfile::model()->find('country_id=:country_id', array(':user_id' => $id));
//echo CHtml::encode($model->getAttributeLabel('country')); ?>:</b>
<?php// echo CHtml::encode($model->name);
?>
<br />
</div>
Now I want to display country name in above view.
These are the relationships of country and user profile table
public function relations() {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'user' => array(self::BELONGS_TO, 'TblUser', 'user_id'),
'country' => array(self::BELONGS_TO, 'country', 'country_id'),
'state' => array(self::BELONGS_TO, 'state', 'state_id'),
'city' => array(self::BELONGS_TO, 'city', 'city_id')
);
}
Use the following code:
<b><?php echo CHtml::encode($data->country->getAttributeLabel('name')); ?>:</b>
<?php echo CHtml::encode($data->country->name); ?>
<br />
Provided that in your country model, the country name column is name.
Since the relation is in place we can use it to access the related country for each user.
In detailview it'll change to:
// instead of 'country_id'
array(
'name'=>'country_id',
'value'=>$model->country->name
)
Read the CDetailView doc to see how you can change even more things.
I would use:
$model = TblUserProfile::model()->with('country')->find('user_id=:user_id', array(':user_id' => $id));
with('country') explained: the string country comes from the array relations key.
Then to display in the view you would use:
$model->country->CountryName;
$model contains
country contains a "model" of country joined by the relation foreign key
CountryName is the column name in the Country table
This is the recommended way to do it in the MVC way. Both my example and the one above work, but the one above has more process/logic decisions in the view, which breaks the concept of MVC where the Model should be the fat one and contain all logic/processing possible, then controller will pull this data and provide it to the view.
You can also follow this below answer:
Just put the below code in your view.php file
[
"attribute"=>"User_Country_Id",
'value' =>$model->country->conName ,
],
[
"attribute"=>"User_State_Id",
'value' =>$model->states->stsName ,
],
[
"attribute"=>"User_City_Id",
'value' =>$model->cities->ctName ,
],
I am new with Yii, Sorry if my question might be stupid, I am using CGridView to show some fields of my database in a table:
<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>
<div class="search-form" style="display:none">
<?php $this->renderPartial('_search',array(
'model'=>$model,
)); ?>
</div><!-- search-form -->
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'show-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'title',
'brief',
'tbl_season_id',
'on_season',
array(
'name'=>'status',
'value'=>'Lookup::item("NewsStatus",$data->status)',
'filter'=> Lookup::items('NewsStatus'),
),
array(
'class'=>'CButtonColumn',
),
),
)); ?>
</div>
I want to replace some of the values that are shown, for example, the on_season field is binary and in the table the values are 0 or 1, I want to change this values to Yes and NO,
And tbl_season_id is a foreign key form another table, I would like to get the name of the season and put it instead of the id which is not understandable by the users.
You can refer this wiki article for customizing your column values to your heart's content
Yii Documentataion: cgridview-render-customized-complex-datacolumns
Just remember that the value property can be an expression string, which is later evaluated for each data of rows. So you have a method call there which can dynamically calculate any value for you depending on the current values of that row.
Let you have two table
1): clients 2): projects
Relation is a client has many projects.
in model
and clients model the relation is (the Client table model name is Client)
class Client extends CActiveRecord{
}
and relations() method ;
return array(
'projects' => array(self::HAS_MANY, 'Projects', 'clients_id'),
);
project model the relation is (the project table model name is Projects)
class Projects extends CActiveRecord{
}
and relations() method ;
return array(
'clients' => array(self::BELONGS_TO, 'Client', 'clients_id')
);
Now
now you can use the following to get the client_name replace the client_id in proejct table
in CGridView
'dataProvider' => $model->search(),
'columns' => array(
'id',
'project_name',
array(
'name' => 'client Name',
'value' => '$data->clients->name', //where name is Client model attribute
),
)
and
Project view page in CDetailView you can use the following
'data' => $model,
'attributes' => array(
'id',
'project_name',
array(
'name'=>'Client Name',
'value'=>$model->clients->name ,
),
)
if you have client relation with company table (a company has many clients )
client model
'company' => array(self::BELONGS_TO, 'Company', 'company_id'),
you can also get the company name by following method in
index (CGridview)
array(
'name' => 'client Name',
'value' => '$data->clients->company->name', //where name is company model attribute
),
and in view CDetailView
array(
'name'=>'Client Name',
'value'=>$model->clients->company->name ,
),
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'
);
//....
),