i got 2 models: Project and Users connected with (User.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(
"projects"=>array(self::MANY_MANY, 'Project','projects_users(user_id, project_id)'),
);
}
I want to show all users in CActiveDataProvider who are not connected with project. How can i do it?
I found solution:
$criteria=new CDbCriteria;
foreach($model->users as $cur) {
$criteria->addCondition("ID != ".$cur->ID);
}
$users=User::model()->findAll($criteria);
$dataProvider2=new CActiveDataProvider('User');
$dataProvider2->data = $users;
Try this:
$users = User::model()->with('projects')->findAll(array(
'together' => true,
'condition' => 'projects.id IS NULL',
));
Related
How to get the count of childCompetency through childDomain which having has many relation
'childDomain' => array(self::HAS_MANY, 'SkillRelDomain', 'skill_id'),
'childCompetency' => array(self::HAS_MANY, 'SkillRelCompetency', 'domain_id'),
Here is a one to many (User:Post) relationship example in Yii 1
In case of post every post belongs to a user. So relation looks like this.
public function relations() {
return array(
'user'=>array(self::BELONGS_TO, 'User', 'iduser'),
);
}
Similarly, a user can have multiple posts. So relation for user as:
public function relations() {
return array(
'posts'=>array(self::HAS_MANY, 'Post', 'iduser'),
);
}
Now when you do a $user = User::model()->findByPk($id), you can have access to relation data also
you can call
foreach($user->posts as $post){
echo $post->name;
}
The data to be extracted are:
->select('ingreso.idingreso', 'ingreso.fecha_hora', 'persona.nombre', 'ingreso.tipo_comprobante', 'ingreso.serie_comprobante', 'ingreso.num_comprobante', 'ingreso.impuesto', 'ingreso.estado', 'SUM("ingreso.cantidad*precio_cantidad") AS total')
the relationships of the models in the tables:
table "ingreso"
public function relations()
{
return array(
'didingreso' => array(self::HAS_MANY,'detalle_ingreso', 'idingreso'),
);
}
table "detalle_ingreso"
public function relations()
{
return array(
'ingres' => array(self::HAS_ONE,'ingreso', 'idingreso'),
'articulo' => array(self::HAS_ONE,'articulo', 'idarticulo'),
);
}
table "articulo"
public function relations()
{
return array(
'idproveed' => array(self::HAS_MANY,'ingreso', 'idproveedor'),
);
}
table "persona"
public function relations()
{
return array(
'idproveed' => array(self::HAS_MANY,'ingreso', 'idproveedor'),
);
}
without the relationships I tried to do this:
$table = Ingreso::find()
->innerJoinWith('persona', 'ingreso.idproveedor = persona.idpersona')
->innerJoinWith('detalle_ingreso', 'ingreso.idingreso = detalle_ingreso.idingreso')
->select('ingreso.idingreso', 'ingreso.fecha_hora', 'ingreso.nombre', 'ingreso.tipo_comprobante', 'ingreso.serie_comprobante', 'ingreso.num_comprobante', 'ingreso.impuesto', 'ingreso.estado', 'SUM("detalle_ingreso.cantidad*detalle_ingreso.precio_venta") AS total')
->andWhere(["estado" => 'A'])
->orderBy(['ingreso.idingreso' => SORT_DESC])
->groupBy(['ingreso.idingreso', 'ingreso.fecha_hora', 'ingreso.nombre', 'ingreso.tipo_comprobante', 'ingreso.serie_comprobante', 'ingreso.num_comprobante', 'ingreso.impuesto', 'ingreso.estado']);
these are my tables:
the error that throws me apparently is when trying to access the result and is the following:
thanks for your help.
If you are using Yii2 you should use the relations statements from yii2 activeRecord.
Here the documentation
EDIT:
You should create all realtions that you need individually and then create a mixed query with with
Your Model:
public function getIngreso(){
return $this->hasMany(Ingreso::className(), ['id' => 'id_ingreso']);
}
public function getDetalleingreso(){
return $this->hasMany(DetalleIngreso::className(), ['id' => 'id_detalleingreso']);
}
In your controller:
$results = $model->find()->select('foo')->with(['ingreso', 'detalleingreso'])->all();
I am working on yii and want a functionality to auto insert created , modified and user_id(my column names in db). I am currently doing this with following way . I have to add this code in every model .
public function rules()
{
return array(
......
array('created, modified', 'default', 'value'=>new CDbExpression('NOW()'), 'setOnEmpty' => false, 'on' => 'insert'),
array('modified', 'default', 'value' => new CDbExpression('NOW()'), 'setOnEmpty' => false, 'on' => 'update'),
array('user_id', 'default', 'value' => Yii::app()->user->id, 'setOnEmpty' => false,'on' => 'insert'),
array('id, feed_id, user_id, text, created, modified', 'safe', 'on'=>'search'),
..........
);
}
this is working on insert and update, But I want is
That if here is a method so that i have to insert it in one file and
no need to insert this in every model . If it is possible
If you have several models and want to implement common behaviour on them, you can use a custom component and use any of given methods in comments and other answers (behaviors, rules, beforeSave, etc) and extending it for all models.
Create a new file in protected/components called for example MasterModel.php. In this example I want to inherit beforeSave method for all models. Fill MasterModel.php with:
<?php
abstract class MasterModel extends ActiveRecord
{
public function beforeSave()
{
$current_time = date('Y-m-d H:i:s');
if ( $this->isNewRecord )
{
$this->created = $current_time;
$this->created_by = Yii::app()->user->id;
}
if ( ! $this->isNewRecord )
{
$this->updated = $current_time;
$this->updated_by = Yii::app()->user->id;
}
return parent::beforeSave();
}
}
Replace on all your existing and future model definitions:
<?php
class Client extends ActiveRecord
{
....
With:
<?php
class Client extends MasterModel
{
....
Make sure to have on your database tables and models:
created DATETIME
created_by INT
updated DATETIME
updated_by INT
You can do this in three ways:
1) Update via model’s rules:
public function rules()
{
return array(
array('title','length','max'=>255),
array('title, created_at, updated_at', 'required'),
array('updated_at','default',
'value'=>new CDbExpression('NOW()'),
'setOnEmpty'=>false,'on'=>'update'),
array('created_at,updated_at','default',
'value'=>new CDbExpression('NOW()'),
'setOnEmpty'=>false,'on'=>'insert'),
array('user_id','default',
'value'=> Yii::app()->user->id,
'setOnEmpty'=>false,'on'=>'insert')
);
}
2) Another to use beforeSave() as follows:
public function beforeSave() {
if ($this->isNewRecord)
$this->created_at = new CDbExpression('NOW()');
$this->user_id = Yii::app()->user->id;
$this->updated_at = new CDbExpression('NOW()');
return parent::beforeSave();
}
3) Another alternative to use CTimestampBehavior in your models:
public function behaviors()
{
return array(
'CTimestampBehavior'=>array(
'class'=>'zii.behaviors.CTimestampBehavior',
'createAttribute'=>'created_at',
'updateAttribute'=>'updated_at',
'setUpdateOnCreate'=>true,
'timestampExpression'=>new CDbExpression('NOW()');
)
);
}
Make sure your every table has same field name created_at, updated_at and user_id.
I found a very usefull article here how to insert autofill yii model data
you just need to create a class as #Alejandro Quiroz answered . The issue in that answer was if field is not available it throws an exception so here is the best solution i found. you need to check if attribute available with if($this->hasAttribute('modified'))
public function beforeSave()
{
$current_time = date('Y-m-d H:i:s');
if ( $this->isNewRecord )
{
if($this->hasAttribute('created'))
$this->created = $current_time;
if($this->hasAttribute('modified'))
$this->modified = $current_time;
if($this->hasAttribute('user_id')) // make sure user field name i user_id
$this->user_id = Yii::app()->user->id;
}
if ( ! $this->isNewRecord )
{
if($this->hasAttribute('modified'))
$this->modified = $current_time;
/* remove this if want updated by id */
//$this->updated_by = Yii::app()->user->id;
}
return parent::beforeSave();
}
I'm trying to join my comment table with my user table like this comment.userId=user.id
unfortunately when i print_r($this->user); i get nothing. what am i doing wrong here?
in my comment model
public function relations()
{
return array(
'user' => array(self::BELONGS_TO, $this->module->user, 'userId'),
);
}
public function getLastName()
{
print_r($this->user);
die;
return is_null($this->user) ? '' : $this->user->{$this->module->lastNameAttribute};
}
where
$this->module->user = 'User'; //User is the model name
and
$this->module->lastNameAttribute = 'last_name';
in my view
$comments = $model->getCommentDataProvider();
$comments->setPagination(false);
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$comments,
'itemView'=>'application.modules.comment.views.comment._view', //view file location
'emptyText' => '<div class="alert alert-info">No comments yet.</div>',
'summaryText' => '<h4>'.Yii::t('commentTitle','{n} comment|{n} comments',$comments->totalItemCount).'</h4>'
));
I see a small typo, maybe you mistaken while making a post:
comment.userid=user.id
here it's userid and in relation you referenced it with userId
check it out please
EDIT - after question edit
I'm not familiar with CommentableBehavior but it seems to me that you need to eager load User model with each Comment:
$comments = Yii::createComponent($this->module->commentModelClass)->with('user')->findAll($this->getCommentCriteria());
I added with('user') in getComments() method
I am new in yii. I want to search by attribute (field name) from my model and need to view in view page or another page by zii.widgets.grid.CGridView.
how can I create a search() function in model by findByAttribute()
so that we can show the results by attribute without any search
here is my model function but it is not working.. :: ERROR Undefined variable: pp_requisitionno
public function searchView()
{
$criteria=new CDbCriteria();
$criteria->select= 'pp_requisitionno';
$criteria->addSearchCondition('pp_requisitionno',$pp_requisitionno);
$criteria->compare('pp_requisitionno',$this->pp_requisitionno);
$criteria->condition = 'pp_requisitionno=:pp_requisitionno';
$criteria->params = array(':pp_requisitionno'=>Yii::app()->Request->Getpost('pp_requisitionno'));
$model = Requisitiondt::model()->find();
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Any help please...
It's probably going to be more useful to define a general search function that can be reused for different searches. This can be done in the following way:
/**
* Retrieves a list of models based on the current search/filter conditions.
* #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search() {
$criteria = new CDbCriteria;
//Define all your searchable fields here
$criteria->compare('t.title', $this->title, true);
$criteria->compare('t.type', $this->type, true);
$criteria->compare('t.published', $this->published, true);
$criteria->compare('category.id', $this->category_id, true);
//Add any other criteria, like the default sort order etc.
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Then in your controller you can use the search like this;
pubic function actionSearch(){
$model = new Requisitiondt;
if (isset($_POST)){
$model->attributes = $_POST;
$dataProvider = $model->search();
$this->render('searchView', array('dataProvider' => $dataProvider));
}
}
The view 'searchView' then looks like this;
<?php
$this->widget('CGridView', array(
'dataProvider' => $dataProvider,
'columns' => array(
//Add in whatever columns you want the grid to show
)
));
?>
Obviously you'll need to replace your own model names and field names, but this is the general idea. This way will search for any attributes you include in the POST request,and is more reusable.
You need use Relations in your model, read here.
Then add 'filter' => $model, in your GridView Widget options array