I have two tables and i need to filter and put those two table data to gridview.i use joined two table like this
$student=new Student;
$marks=new AssimentMarks;
$criteria_st=new CDbCriteria;
$criteria=new CDbCriteria;
$criteria->select = 't.st_id,t.st_name,stu.ass_id,stu.marks_cr1,stu.marks_cr2,stu.marks_cr3,stu.marks_cr4,stu.marks_cr5';
$criteria->join = 'INNER JOIN assiment_marks stu ON stu.st_id=t.st_id';
$criteria->condition = 'stu.ass_id=:ass_id';
$criteria->params = array(':ass_id'=>Yii::app()->session['modelcrite']['ass_id']);
$criteria->addInCondition('t.st_id', $studentid);
return new CActiveDataProvider($student, array('criteria'=>$criteria,));
but in gridviwe only show the student database values.it is show as .how can i pass two models to CActiveDataProvider ?
this is how data shows
http://i.stack.imgur.com/Kogjz.jpg
1) Foreign key in schema
Your assiment table should reference your student table with a foreign key, like this (assuming SQLite):
CREATE TABLE student (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE assiment_record(
id INTEGER PRIMARY KEY,
student_id INTEGER,
cr1 INTEGER,
cr2 INTEGER,
cr3 INTEGER,
cr4 INTEGER,
cr5 INTEGER,
FOREIGN KEY( student_id ) REFERENCES student(id) -- FK goes in the CHILD table.
);
2) Generate models with Gii:
student -> models/Student.php
assiment_record -> models/AssimentRecord.php
Gii is smart and guesses your relations:
// AssimentRecord.php looks good! No changes made!
public function relations()
return array(
'student' => array(self::BELONGS_TO, 'Student', 'student_id'),
);
The assiment record BELONGS TO the student.
3) Tweak gii's output (Student.php)
But Gii's is not perfect, and does not know what your intentions are. The current student relation (HAS_MANY) returns an array, but I don't want to deal with the array (because I'm lazy!), so I change it into a HAS_ONE-relation instead:
// Student.php
public function relations()
{
return array(
// Change this: 'assimentRecords' => array(self::HAS_MANY, 'AssimentRecord', 'student_id'),
/* into this: */ 'assimentRecord' => array(self::HAS_ONE, 'AssimentRecord', 'student_id'),
);
}
The student HAS ONE assiment record.
4) Display the grid:
// views/site/index.php (Or wherever.)
$dataProvider = new CActiveDataProvider( 'Student' );
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns' => array(
'id',
'name',
'assimentRecord.cr1',
'assimentRecord.cr2',
'assimentRecord.cr3',
'assimentRecord.cr4',
'assimentRecord.cr5',
)
));
Related
1. Table meeting
Model name CoreMeeting
Fields id, title, start time, created_by
Relationship:
'MeetingParticipants' => array(self::HAS_MANY, 'MeetingParticipants', 'meeting_id'),
2. Table core_meeting_participant
Model name is meeting_participant
Fields are id, meeting_id, participant_id, group_id
Relationship:
'meeting' => array(self::BELONGS_TO, 'CoreMeeting', 'meeting_id'),
'group' => array(self::BELONGS_TO, 'MeetingGroup', 'group_id'),
3. Table core_meeting_group
Model name is MeetingGroup
Fields are id, group_name
My search filter in the meeting model is:
public function search()
{
$group=filter_var($_REQUEST['group'], FILTER_SANITIZE_STRING);//contain group name
$criteria=new CDbCriteria;
$user_id = Yii::app()->user->id;
$criteria->compare('id',$this->id);
$criteria->compare('title',$this->title,true);
$criteria->with=array('MeetingParticipants'=>array("select"=>"*"),'MeetingParticipants.group'=>array('select'=>'id,group_name'));
if(isset($this->start_time) && !empty($this->start_time))
$criteria->compare('start_time',date("Y-m-d", strtotime($this->start_time)), true);
$criteria->compare('created_by',$user_id);
if(isset($group)&&!empty($group))
$criteria->compare('group.group_name',$group);
$criteria->together = true;
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
I have created 4 meetings, each meeting have at least 5 participants each participant belongs to a meeting group. I want to list all meetings with the following filed meeting title, groups and meeting time.
My problem is if I enable $criteria->together = true; if the meeting has more than 10 participants that will show only 1 meeting in grid view. If I disable this that will show all but I can't search with the meeting name.
SQL fiddle link is http://sqlfiddle.com/#!9/fdaacf
full SQL dump https://pastebin.com/NtpMuCpE
Documentation for CDbCriteria->together property:
https://www.yiiframework.com/doc/api/1.1/CDbCriteria#together-detail
Whether the foreign tables should be joined with the primary table in a single SQL. This property is only used in relational AR queries for HAS_MANY and MANY_MANY relations.
As I can see your relation in CoreMeeting model:
'group' => array(self::BELONGS_TO, 'MeetingGroup', 'group_id')
Obviously you are trying to fetch one-to-one (BELONGS_TO) relation CoreMeeting -> MeetingGroup eagerly by globally setting to your CDbCriteria->together = true; which is not correct according to the documentation.
What I would suggest you, first of all get rid of this global together setting to CDbCriteria and try changing your with clause like this:
$criteria->with = [
// this is your has-many relation (one meeting has several participants), thus we set here `together` to true
'MeetingParticipants' => [
'together' => true,
'with' => [
// this is your one-to-one relation (one participant has one group)
'group'
]
]
];
I have this Object model with 'has_many' relation to Variables
public function relations()
{
return array(
'variables' => array(self::HAS_MANY, 'Variables', 'variable_id')
);
}
Now i want to use the variables to order my data like
$criteria->with = array('variables');
$criteria->order = 'variables.id DESC';
But it doesn't work.
Is there a way to do something like this? Thanks.
You can define the relation directly with an order if you want, in this case you can do.
public function relations()
{
return array(
'variables' => array(self::HAS_MANY, 'Variables', 'object_id', 'order'=>'variables.id DESC')
);
}
What you wrote it is not working because you have a 1 to many relation. The criteria will run 2 queries, 1 to get the main record, the second time to get the relations. That is why your order is not working.
If you want it to work like you said you should do a ->join instead of ->with.
There is quite a difference between the 2 so take care how you are writing the criteria.
I think the issue is with foreign key binding, if you are adding a relationship in object table (Object model) which has many variables having object_id as foreign key in variable table (Variable model) then you need to define relationship as follows:
public function relations()
{
return array(
'variables' => array(self::HAS_MANY, 'Variables', 'object_id') // check the change in foreign key column
);
}
I want do a project with YiiFramework.
in this project I have 1 table that have many relation
I want create a form that insert data in main table and all relation
for example :
I want a form that add student information
I have 2 table
first : id name family
and
second: id student_id field
I want add data in table 1 and then add data in table 2
and all of the this jobs do in a form
do u have any solution for that?
my really reations :
'homehouse' => array(self::HAS_ONE, 'Homehouse', 'HouseId'),
'houseType' => array(self::BELONGS_TO, 'Parametervalues', 'HouseTypeId'),
'owner' => array(self::BELONGS_TO, 'Person', 'OwnerId'),
'region' => array(self::BELONGS_TO, 'Region', 'RegionId'),
'housemultimedias' => array(self::HAS_MANY, 'Housemultimedia', 'HouseId'),
'housestages' => array(self::HAS_MANY, 'Housestage', 'HouseId'),
'tradehouse' => array(self::HAS_ONE, 'Tradehouse', 'HouseId'),
You have to do it with each model, so, let's say you have 2 models (student and job) and you're sending the data from the form with POST method.
Them, in your controller, you save first the main data and second the relation, for example: (ps. this is just a hypothetical example)
Controller
public function actionSave(){
if(isset($_POST['Student'])) {
$Student = new Student();
$Student->Job = new Job();
$Student->attributes = $_POST['Student'];
$Student->Job->attributes = $_POST['Job'];
if($Student->save()){
$Student->Job->student_id = $Student->id;
$Student->Job->save();
}
}
}
With this idea, you can save the data in many relations that you model has.
Reference: How to save related objects?
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'
);
//....
),
taxonomies
-id
-name
taxonomy_type
-taxonomy_id
-type_id
I've configured two models:
class Model_Taxonomy{
protected $_has_many = array('types'=>array());
}
class Model_Taxonomy_Type{
protected $_belongs_to = array('taxonomy' => array());
}
*Please note that taxonomy_type is not a pivot table.*
A taxonomy can have multiple types associated.
Then, what I'm trying to do is get all taxonomies that belong to a given type id.
This is would be the SQL query I would execute:
SELECT * FROM taxonomies, taxonomy_type WHERE taxonomy_type.type_id='X' AND taxonomies.id=taxonomy_type.taxonomy_id
I've tried this:
$taxonomies = ORM::factory('taxonomy')
->where('type_id','=',$type_id)
->find_all();
Obviously this doesn't work, but I can't find info about how execute this kind of queries so I have no clue.
class Model_Taxonomy{
protected $_belongs_to = array(
'types' => array(
'model' => 'Taxonomy_Type',
'foreign_key' => 'taxonomy_id'
)
);
}
class Model_Taxonomy_Type{
protected $_has_many = array(
'taxonomies' => array(
'model' => 'Taxonomy',
'foreign_key' => 'taxonomy_id'
)
);
}
And use some like that:
$type = ORM::factory('taxonomy_type')
->where('type_id', '=', $type_id)
->find();
if( ! $type->taxonomies->loaded())
{
types->taxonomies->find_all();
}
type_id column is a PK of taxonomy_type table, am I right?
So, you have one (unique) taxonomy_type record, and only one related taxonomy object (because of belongs_to relationship). Instead of your:
get all taxonomies that belong to a
given type id
it will be a
get taxonomy for a given type id