I have a football match function. But always display same team on home or away.
Here's my code,
Model [Match] :
use app\models\Team;
...
public function getTeam()
{
return $this->hasOne(Team::className(), ['id' => 'home', 'id' => 'away']);
}
...
Team model is list of all team
Match table only keep id of Team on Home Field and Away Field
Model [MatchSearch] :
....
public $team_home;
public $team_away;
public function rules()
{
return [
[['home', 'away'], 'integer'],
[['team_home', 'team_away'], 'safe'],
];
}
...
public function search($params)
{
$query = Match::find()->joinWith(['team']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['team_home'] = [
'asc' => ['team.team' => SORT_ASC],
'desc' => ['team.team' => SORT_DESC],
];
$dataProvider->sort->attributes['team_away'] = [
'asc' => ['team.team' => SORT_ASC],
'desc' => ['team.team' => SORT_DESC],
];
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$query->andFilterWhere([
'home' => $this->home,
'away' => $this->away,
]);
$query->andFilterWhere(['like', 'team.team', $this->team_home])
->andFilterWhere(['like', 'team.team', $this->team_away]);
return $dataProvider;
}
Views [Index] :
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'home',
'value' => function($data) {
return $data->team->team;
},
],
[
'attribute' => 'away',
'value' => function($data) {
return $data->team->team;
},
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php Pjax::end(); ?>
But the result always show the Away team both Home or Away :
Home :
Team Away
Away :
Team Away
How to fix this?
You can use inner join
$query = Match::find()
->innerJoin('team_tname as home', '`team_taame`.`id` = `match_table_name`.`home`')
->innerJoin('team_taname as away', '`team_name`.`id` = `match_table_name`.`away`');
the you should refer to the column name using the proper table alias
Related
I want to use Select2 dr as filter in Yii Grid view, but it doesn't filter at all, only refreshes the page.
I take the data from 2 tables - from accounts I take only user_id, and from credits I take everything else. And every filter works, except And the 'user_id' one.
<?php
echo GridView::widget(
[
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'wp_id',
'value' => 'accounts.user_id',
'filter' => Select2::widget(
[
'model' => $searchModel,
'attribute' => 'wp_id',
'data' => ArrayHelper::map(Accounts::find()->all(), 'wp_id', 'user_id'),
'options' => ['placeholder' => ' --Filter by user id-- '],
'language' => 'en',
'pluginOptions' => [
'allowClear' => true,
],
]
),
],
],
]
); ?>
Here is the action in the controller.
<?php
public function actionIndex()
{
$searchModel = new CreditsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
} ?>
And this is the search model method
<?php
public function search($params)
{
$query = Credits::find()->with('accounts');
$dataProvider = new ActiveDataProvider([
'query' => $query
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
if(!empty($this->user_id)) {
$query->andFilterWhere(['=', 'accounts.user_id', $this->user_id]);
}
// grid filtering conditions
$query->andFilterWhere([
'user_id' => $this->user_id,
'wp_id' => $this->wp_id,
'credits_bought' => $this->credits_bought,
'purchase_date' => $this->purchase_date,
'id' => $this->id,
]);
return $dataProvider;
}
} ?>
Thanks in advance!
Because you are passing the wp_id under the GridView filter and selecting the wp_id from the Accounts model as the value of the select2-dropdown
ArrayHelper::map(Accounts::find()->all(), 'wp_id', 'user_id')
Although it is confusing that you use the gridview column attribute wp_id and use the select2 to filter the user_id for the same column but if you are looking to do that you might need to change the above to
ArrayHelper::map(Accounts::find()->all(), 'user_id', 'wp_id')
In Yii2 app I have model Document which can belong to user. Belonging is set with owner_id field.
In view I display list of Documents using GridView widget. Default sort is by document_id.
Every user sees all documents (event if specific document doesn't belong to him).
But I need to display documents which belongs to current logged in user at the top of GridView. How can I do this?
I suppose I should make some changes to Document::search() method by can't find out what excactly I should do.
Here is my controller action:
public function actionIndex()
{
$modelFullName = $this->modelFullName;
$model = new $modelFullName();
$dataProvider = $model->search(Yii::$app->request->queryParams);
return $this->render(
'index',
[
'model' => $model,
'dataProvider' => $dataProvider,
]
);
}
Part of view:
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $model,
'columns' => [
[
'attribute' => 'document_id',
],
[
'attribute' => 'status',
'format' => 'raw',
'value' => function($model) {
return $model->statusString;
},
],
[
'attribute' => 'title',
],
[
'attribute' => 'date_created'
],
[
'attribute' => 'client_id',
'value' => function($model) {
return $model->client ? $model->client->title : '';
},
'filter' => ArrayHelper::map(Clients::find()->all(), 'client_id', 'title')
],
[
'attribute' => 'project_id',
'value' => function($model) {
return $model->project ? $model->project->title : '';
},
'filter' => ArrayHelper::map(Projects::find()->all(), 'project_id', 'title')
],
[
'class' => yii\grid\ActionColumn::className(),
'template' => '{view} {delete}',
'buttons' => [
'view' => function ($url, $model) {
return $this->context->getBtn('view', $model);
},
'delete' => function ($url, $model) {
if (Yii::$app->user->can('deletePrsSum')) {
return $this->context->getBtn('delete', $model);
}
},
],
'visibleButtons' => [
'update' => Yii::$app->user->can('updateDocument'),
'delete' => Yii::$app->user->can('deleteDocument'),
]
],
],
]);
Current Document::search() implementation:
public function search($params)
{
$query = self::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => ['document_id' => SORT_ASC]
]
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
if ($this->client_id) {
$query->andFilterWhere([
'client_id' => $this->client_id,
]);
}
if ($this->project_id) {
$query->andFilterWhere([
'project_id' => $this->project_id,
]);
}
return $dataProvider;
}
UPDATE
So how I managed to do this:
public function search($params)
{
$userId = Yii::$app->user->identity->user_id;
$query = self::find()->select(
"*, IF(owner_id={$userId},(0),(1)) as sort_order"
)->orderBy([
'sort_order' => SORT_ASC,
'document_id' => SORT_ASC
]);
//further code...
Add a filter in your search function to filter with the id of the logged in person/user:
$query->andFilterWhere(['owner_id' => Yii::$app->user->identity->id]);
i want to join my company table name to employee id. here my code in
employee model
public function attributeLabels()
{
return [
'id' => 'ID',
//'company_id' => 'Company ID',
'emp_name' => 'Emp Name',
'emp_email' => 'Emp Email',
'emp_salery' => 'Emp Salery',
];
}
public function getCompany()
{
return $this->hasOne(Company::className(),['id' => 'company_id']);
}
in index file i use this code
<?php PJax::begin();?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
//['class' => 'yii\grid\SerialColumn'],
//'id',
[
'attribute' => 'company_id',
'value' => 'company.name',
],
'emp_name',
'emp_email:email',
'emp_salery',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php PJax::end();?></div>
in employee search table i use this code
public function search($params)
{
$query = Employee::find();
$query->joinWith(['company']);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
$query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
]);
$query->andFilterWhere(['like', 'company_id', $this->company_id])
->andFilterWhere(['like', 'emp_name', $this->emp_name])
->andFilterWhere(['like', 'emp_email', $this->emp_email])
->andFilterWhere(['like', 'emp_salery', $this->emp_salery])
->andFilterWhere(['like', 'Company.name', $this->company_id])
->andFilterWhere(['like', 'company.name', $this->company])
;
return $dataProvider;
}
http://localhost/test/web/employee/
is shows in company field (not set)
pls help me
you can do this in two difference way : 1 . If you want use active record you must set property in first model you want to select it and join table with that like:
public $pin;
then when you get data you can access to pin in second table
the second way is you use asArray() that return all off data in both table
$model = News::find()->leftJoin('comment', 'news.id = comment.news_id')->asArray()->all();
then you can use it in your gridview
You should add a getter eg:getCompanyname()n your base model
......
public function attributeLabels()
{
return [
'id' => 'ID',
//'company_id' => 'Company ID',
'emp_name' => 'Emp Name',
'emp_email' => 'Emp Email',
'emp_salery' => 'Emp Salery',
'companyName' => 'Company Name')
];
}
public function getCompany()
{
return $this->hasOne(Company::className(),['id' => 'company_id']);
}
You should add a getter for company name
/*
Getter for company name
*/
public function getCommpanyName() {
return $this->company->name;
}
and in your gridview you should use the new get name (companyName)
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'companyName',
'emp_name',
'emp_email:email',
'emp_salery',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
see this for more complete samples
http://www.yiiframework.com/wiki/621/filter-sort-by-calculated-related-fields-in-gridview-yii-2-0/
I have 3 tables named hostgroup, host and services.
I have a database like this for example.
Hostgroup:
id, name
1 GroupA
2 GroupB
Host:
id, name, hostgroup_id
1 HostA 1
2 HostB 1
3 HostC 2
4 HostD 2
5 HostE 2
//2 = critical, 1 = warning
Service:
id, host_id, state
1 1 2
2 1 2
3 2 1
4 2 1
5 3 2
The final table should be like this:
Name Total Hosts Total Critical Total Warning
GroupA 2 2 2
GroupB 3 1 0
I was able to do the 2nd column which is Total Hosts by adding this function on my Hostgroup model:
public function getHostcount()
{
return Host::find()->where(['hostgroup_id' => $this->id])->count();
}
How can I count the total warning and critical also?
Total critical (counts the number of total critical status of hosts related to the hostgroup)
Total warning (counts the number of total warning status of hosts related to the hostgroup)
EDIT: ADDED SOURCE CODE
HostgroupSearch model:
<?php
class HostgroupSearch extends Hostgroup
{
public function rules()
{
return [
[['id', 'check_interval', 'retry_interval', 'max_check_attempts', 'timeout', 'freshness_threshold', 'is_auto_recovery', 'reflect_flg', 'created_user_id'], 'integer'],
[['object_name', 'name', 'name_search', 'remarks', 'snmp_community', 'timestamp'], 'safe'],
];
}
public function search($params)
{
$query = Hostgroup::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'check_interval' => $this->check_interval,
'retry_interval' => $this->retry_interval,
'max_check_attempts' => $this->max_check_attempts,
'timeout' => $this->timeout,
'freshness_threshold' => $this->freshness_threshold,
'is_auto_recovery' => $this->is_auto_recovery,
'reflect_flg' => $this->reflect_flg,
'created_user_id' => $this->created_user_id,
'timestamp' => $this->timestamp,
]);
$query->andFilterWhere(['like', 'object_name', $this->object_name])
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'name_search', $this->name_search])
->andFilterWhere(['like', 'remarks', $this->remarks])
->andFilterWhere(['like', 'snmp_community', $this->snmp_community]);
return $dataProvider;
}
}
This HostlistController controls the display of everything in my table.
<?
class HostlistController extends Controller
{
public $layout = "default";
public function actionIndex()
{
$searchModel = new HostgroupSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
}
?>
This is then my view page index.php:
'columns' => [
[
'label' => 'Name',
'attribute' => 'name',
'format' => 'raw',
'value' => function ($data, $id) {
return Html::a($data->name, '/index.php/hostlistbygroup/'. $id);
},
],
[
'label' => 'Total Host',
'attribute' => 'hostcount',
],
[
'label' => 'Total Critical',
'attribute' => 'host.criticalcount',
],
[
'label' => 'Total Warning',
'attribute' => 'host.warningcount',
],
Nevermind. Solved it by adding these functions to Host model.
public function getCriticalcount()
{
return ServiceStatuses::find()->where(['host_id' => $this->id, 'last_hard_state' => '2'])->count();
}
public function getWarningcount()
{
return ServiceStatuses::find()->where(['host_id' => $this->id, 'last_hard_state' => '1'])->count();
}
and added this to Hostgroup model
public function getHost()
{
return $this->hasOne(Host::className(), ['hostgroup_id' => 'id']);
}
modified index.php with this
'columns' => [
[
'label' => 'Name',
'attribute' => 'name',
'format' => 'raw',
'value' => function ($data, $id) {
return Html::a($data->name, '/index.php/hostlistbygroup/'. $id);
},
],
[
'label' => 'Total Host',
'attribute' => 'hostcount',
],
[
'label' => 'Total Critical',
'attribute' => 'host.criticalcount',
],
[
'label' => 'Total Warning',
'attribute' => 'host.warningcount',
],
I have Post model and two related models, User and Comments.
Relation with User and Comment model defined in Post model:
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
public function getUserName()
{
return $this->user->name;
}
public function getComments(){
return $this->hasMany(Comment::className(), ['comment_id' => 'id']);;
}
public function countCommentPoints() {
return $this->hasMany(Comment::className(), ['comment_id' => 'id'])->sum('point');
}
My PostSearch model looks like following. I omitted the code andFilterWhere() because it is out of the scope:
class PostSearch extends Post {
public $userName;
public function rules()
{
return ['userName', 'safe'];
}
public function search($params) {
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->setSort([
'attributes' => [
'userName' => [
'asc' => ['user.name' => SORT_ASC],
'desc' => ['user.name' => SORT_DESC],
],
],
]);
if (!($this->load($params) && $this->validate())) {
$query->joinWith(['user']);
return $dataProvider;
}
}
return $dataProvider;
}
View code:
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
'title',
[
'attribute' => 'userName',
'value' => 'userName',
'label' => 'User Name'
],
[
'attribute' => 'comment',
'value' => function($model){
return $model->countCommentPoints();
},
'label' => 'Points',
],
],
]);
With all the code above I could sort the records by id and title and by userName which is an attribute of the related User model. But I could not sort by the column Points since it is not an attribute of the Comment model but a sum value returned from the getLeadEarningPerWebmaster() method. I have tried to read Yii 2.0 documentation here http://www.yiiframework.com/doc-2.0/guide-output-data-widgets.html but the section Sorting Data is still under development. How can I make GridView sort by the Points column?
You can sort GridView columns by related columns that are not necessarily inside the original ActiveRecord.
echo GridView::widget([
'dataProvider' => new ActiveDataProvider([
'query' => $model->joinWith([
'comment' => function ($query) {
$query->select('SUM(point) AS sum')->from(['comment' => '{{%comment}}']);
}
]),
'sort' => [
'attributes' => [
'comment.sum' => [
'asc' => ['comment.sum' => SORT_ASC],
'desc' => ['comment.sum' => SORT_DESC],
]
],
'sortParam' => 'post-sort',
'defaultOrder' => ['comment.sum' => SORT_ASC]
],
]),
That should get you started.