I am battling with CGridView filtering using the related model column, I have two models Cars and Colour, so Colour has_many Car and Car belongs_to Colour. The grid column from related model displays fine, I'm just not able to filter with it. I am getting mysql error
Column not found: 1054 Unknown column 'carName'
Colour model HAS_MANY - Cars
I declaired the variable $carName from the Car model, so this model can see it.
public $carName;
public function rules()
{
return array(
array('id, carName, colourName', 'safe', 'on'=>'search'),
)
}
public function relations()
{
return array(
'CarsObj'=>array(self::HAS_MANY, 'Cars', 'colourID')
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->with = "CarsObj";
$criteria->compare('carName', $this->carName, true);
$criteria->compare('id',$this->id);
$criteria->compare('colourName',$this->colourName,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Car Model BELONGS_TO - Colour
public function relations()
{
return array(
'ColourObj'=>array(self::BELONGS_TO, 'Colour', 'colourID')
);
}
CGridView, i am using the Colour Model search as my dataProvider
$model = new Colour('search');
$data = $model->search();
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$data
,'filter'=>$model
,'pager'=>array('header'=>'')
,'columns'=>array( //related model column
'id',
'colourName',
array(
'header' => 'carName',
'type' => 'raw',
'name' => 'carName',
'value' => function($data, $row) { //$data is item of DataProvider, $row is number of row (starts from 0)
$carNames= CHtml::listData((array)$data->ColourObj, 'id', 'carName');
return implode(', ', $carNames);
}
)
By default CActiveRecord using lazy load. You need to set attribute together true. Also it's a good practice to set table alias when you using with.
public function search(){
$criteria=new CDbCriteria;
$criteria->together = true;
$criteria->with = 'CarsObj';
$criteria->compare('CarsObj.carName',$this->carName,true);
$criteria->compare('t.id',$this->id);
$criteria->compare('t.colourName',$this->colourName,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Try this
public function search()
{
$criteria=new CDbCriteria;
$criteria->with = "CarsObj";
$criteria->compare('CarsObj.carName', $this->carName, true);
$criteria->compare('id',$this->id);
$criteria->compare('colourName',$this->colourName,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Related
I am using Microsoft SQL Server as my database and yii1.1 framework
$model = new Test();
$model->name = "test";
$model->save();
echo $model->id;
I can't get the id this way shown above the code. It doesn't return anything but the data is being saved to the database.
Here is my test class which I have generated through gii
<?php
class Test extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'test';
}
public function rules()
{
return array(
array('name', 'length', 'max'=>10),
array('id, name', 'safe', 'on'=>'search'),
);
}
public function relations()
{
return array(
);
}
public function attributeLabels()
{
return array(
'id' => 'ID',
'name' => 'Name',
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('name',$this->name,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
}
I want to make a custom widget like one of the examples that yii brings (blog), and the custom widget i want to make is the one called "RecentPosts", but for my page i'm going to call it "RecentTasks", so i just want to get the firsts 4 tasks on my database SQLite(almos like "recentPost" does).
in my column2:
<?php /* #var $this Controller */ ?>
<?php $this->beginContent('//layouts/main'); ?>
<div class="col-xs-12 col-sm-9">
<div id="content">
<?php echo $content; ?>
</div><!-- content -->
</div>
<div id="sidebar" class="col-xs-6 col-sm-3 sidebar-offcanvas" role="navigation">
<div class="list-group">
<?php
// $this->beginWidget('zii.widgets.CPortlet', array(
// 'title'=>'Operations',
// ));
$this->widget('zii.widgets.CMenu', array(
'items'=>$this->menu,
'htmlOptions'=>array('class'=>'nav nav-pills nav-stacked'),
));
// $this->endWidget();
?>
<?php
$this->widget('recentTasks', array(
'maxTasks'=>10
));
?>
</div>
</div>
<?php $this->endContent(); ?>
in my custom widget inside components:
<?php
Yii::import('zii.widgets.CPortlet');
class RecentTasks extends CPortlet
{
public $title = 'Recent Tasks';
public $maxTasks = 10;
public function getRecentTasks()
{
return Task::model()->findRecentTasks($this->maxTasks);
}
protected function renderContent()
{
$this->render('recentTasks');
}
}
my model:
<?php
class Task extends CActiveRecord
{
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'task';
}
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('Name, Status, Project_id, User_id', 'required'),
array('Status, Project_id, User_id', 'numerical', 'integerOnly'=>true),
array('Name, Create_time, Update_time, Assigned', 'length', 'max'=>45),
array('Description, Tags', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, Name, Description, Status, Create_time, Update_time, Tags, Project_id, User_id, Assigned', 'safe', 'on'=>'search'),
);
}
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(
'comments' => array(self::HAS_MANY, 'Comment', 'Task_id'),
'project' => array(self::BELONGS_TO, 'Project', 'Project_id'),
'user' => array(self::BELONGS_TO, 'User', 'User_id'),
);
}
public function attributeLabels()
{
return array(
'id' => 'ID',
'Name' => 'Name',
'Description' => 'Description',
'Status' => 'Status',
'Create_time' => 'Create Time',
'Update_time' => 'Update Time',
'Tags' => 'Tags',
'Project_id' => 'Project',
'User_id' => 'User',
'Assigned' => 'Assigned',
);
}
public function findRecentTasks($limit=10)
{
$this->findAll();
}
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('Name',$this->Name,true);
$criteria->compare('Description',$this->Description,true);
$criteria->compare('Status',$this->Status);
$criteria->compare('Create_time',$this->Create_time,true);
$criteria->compare('Update_time',$this->Update_time,true);
$criteria->compare('Tags',$this->Tags,true);
$criteria->compare('Project_id',$this->Project_id);
$criteria->compare('User_id',$this->User_id);
$criteria->compare('Assigned',$this->Assigned,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
in the view of the widget im just making var_dump($this->getRecentTasks());
i haven't figure out the problem but for now its just returning NULL. I followed almost the exact same steps made on the example page in yii
Try this:
// location: /protected/components/RecentTasks.php
class RecentTasks extends CWidget
{
public $title = 'Recent Tasks';
public $maxTasks = 10;
/**
* Is called when $this->beginWidget() is called
*/
public function init()
{
}
/**
* Is called when $this->endWidget() is called
*/
public function run()
{
// render /protected/components/views/recentTasks.php
$this->render('recentTasks', array(
'models'=>$this->getRecentTasks($this->maxTasks)
));
}
public function getRecentTasks()
{
return Task::model()->findRecentTasks($this->maxTasks);
}
}
Call the widget like so in your view or layout file (with a capital):
$this->widget('RecentTasks', array(
'maxTasks'=>10
));
Then you can use $models in the view to show the tasks.
Also see: http://www.yiiframework.com/doc/guide/1.1/en/basics.view#widget
EDIT:
Seems the problem is in your findRecentTasks() method, add return before the findAll(). I also added the code to apply the limit and for conditions may you need that in the future.
public function findRecentTasks($limit=10)
{
return $this->findAll(array(
// 'condition'=>'id = :id',
// 'params' => array('id'=>$id),
'limit'=>$limit
));
}
Problem in accessing the load modules,when migrated to Linux servers.
It does not show any errors but failed to fetech the results.
Works fine in windows os.
Initial problem was the table names case sensitive in Linux and window non-case sensitive.
I renamed the table names
RENAME TABLE main TO Main
Model
class ListModel extends CActiveRecord {
const STATUS_PENDING = 0;
public static function model($className=__CLASS__) {
return parent::model($className);
}
public function tableName() {
return 'list_model';
}
public function rules() {
return array(
array('list_id,list_title,list_user,list_status', 'required'),
array('list_title', 'length', 'max' => 255),
array('list_id,list_status', 'numerical', 'integerOnly' => true),
);
}
public function attributeLabels() {
return array(
'list_id' => 'Id',
'list_title' => 'Title',
'list_user' => 'User',
'list_status' => 'Status',
);
}
public function search(){
$criteria = new CDbCriteria();
$criteria->compare('list_id',$this->list_id, true);
$criteria->compare('list_title',$this->list_title, true);
$criteria->compare('list_user',$this->list_user
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array('defaultOrder'=>'daillisting_complain_id DESC'),
));
}
public static function getCountPending(){
$sql = "SELECT COUNT('list_id') FROM list_model WHERE list_status=".self::STATUS_PENDING;
return (int) Yii::app()->db
->createCommand($sql)
->queryScalar();
}
}
//View
$pending = ListModel::getCountPending();
//does not returns any result and fails
what is the error with the models not fetching the data
While in Windows server they are not Case sensitive
But Whereas in the Linux it is case sensitive.
You Could Check for the Naming convention for controllers,models
Hope this will help you
I have a table Friend (PersonA, PersonB). These are foreign keys of Person(id, name).
I want to create a Yii relation between them. This is what I have come up with:
public function relations() {
return array(
'friends1' => array(self::HAS_MANY, 'Friend', 'PersonA'),
'friends2' => array(self::HAS_MANY, 'Friend', 'PersonB'),
);
}
Is there a way to combine these two relations into one? I was hoping for something like this:
public function relations() {
return array(
'allFriends' => array(self::HAS_MANY, 'Friend', 'PersonA, PersonB'),
);
}
Any ideas?
EDIT #1:
For completeness, let's also imagine that I want to order friends1 and friends2 like this:
public function relations() {
return array(
'friends1' => array(self::HAS_MANY, 'Friend', 'PersonA', 'order'=>'id ASC'),
'friends2' => array(self::HAS_MANY, 'Friend', 'PersonB', 'order'=>'id ASC'),
);
}
This solution worked for me :
Override the __get function in your model:
public function __get($name)
{
if(($name == 'friends1') || ($name == 'friends2')) {
return parent::__get('friends1') + parent::__get('friends2');
}
else
return parent::__get($name);
}
I had the exact same thing come up in something I was working on. What I did is I created another function to compile the two relations into one array. The reason for this is because even if you were to get the two relationships combined, each time you would still need to test to see if PersonA or PersonB is the current user's id and use the other id to pull the Friends info. Here is the function I created in my model:
public function getFriends() {
$all_friends = array();
foreach($this->friends1 as $friend) {
if($friend->PersonA == $this->id) {
$all_friends[] = $friend->PersonA;
} else {
$all_friends[] = $friend->PersonB;
}
}
foreach($this->friends2 as $friend) {
if($friend->PersonA != $this->id) {
$all_friends[] = $friend->PersonA;
} else {
$all_friends[] = $friend->PersonB;
}
}
return $all_friends;
}
Another options:
public function getFriends() {
$criteria = new CDbCriteria;
$criteria->compare('PersonA',$this->id);
$criteria2 = new CDbCriteria;
$criteria2->compare('PersonB',$this->id);
$criteria->mergeWith($criteria2,'OR');
$friends = Challenge::model()->findAll($criteria);
return $friends;
}
Then for any Person you can just say:
$person = Person::model()->findByPk(1);
$friends = $person->friends;
Or instead of an array you could send back an CActiveDataProvider that you could do sorts and other things with. You could do this:
public function getFriends() {
$criteria = new CDbCriteria;
$criteria->compare('PersonA',$this->id);
$criteria2 = new CDbCriteria;
$criteria2->compare('PersonB',$this->id);
$criteria->mergeWith($criteria2,'OR');
return new CActiveDataProvider('Friend', array(
'criteria' => $criteria,
));
}
Then since you have CActiveDataProvider you can sort:
$friends = $user->friends->getData(); //not sorted or anything
//or you can manipulate the CActiveDataprovider
$data = $user->friends;
$data->setSort(array(
'defaultOrder'=>'PersonA ASC',
));
$friends = $data->getData();
I have the following table structure.
tb_posts has the field author_id which relates to tb_author.id
in YII i have the following in my posts activeRecord
public function relations()
{
return array(
'authorRelation' => array(self::BELONGS_TO, 'authorRecord', 'author')
);
}
How i do a search of posts of an authors with name 'foo'? I am trying the following with no success
$criteria=new CDbCriteria;
$criteria->with = array('authorRelation');
$criteria->together = true;
$criteria->compare( 'author.name', 'foo', true );
$posts=PostsRecord::model()->findAll($criteria);
Set table alias for your models at init.
class PostsRecord extends CActiveRecord
{
// ...
public function init() { $this->setTableAlias( 'postsrecord' ); }
// ...
}
class AuthorRecord extends CActiveRecord
{
// ...
public function init() { $this->setTableAlias( 'authorrecord' ); }
// ...
}
Finally:
$condition=new CDbCriteria;
$condition->with = array('authorRelation');
$condition->together = true;
$condition->condition = 'authorrecord.name=:authorname';
$condition->params = array( ':authorname' => 'foo' );
$posts=PostsRecord::model()->findAll($condition);
Your relation should be 'authorRelation' => array(self::BELONGS_TO, 'authorRecord', author_id'). The 3rd parameter is the foreign key.
The second part of the code doesn't have any errors, the search should work if you set up the relations correctly.