I want to multiply two columns in the yii2 grid the grid view is as follows
<?= GridView::widget([
//'dataProvider' => $dataProvider,
'dataProvider'=>new ActiveDataProvider([
'query' => Adanalytics::find()->
where(['publisher_id' => Yii::$app->user->identity->id ])->
select('id,ad_id,MAX(impression) AS impression, MAX(view) AS view, MAX(clicks) AS clicks,MAX(cpc) AS cpclick,MAX(cpv) AS cpview, (MAX(clicks)*MAX(cpc)) AS totalccost')->
groupBy('ad_id, visitor_ip'),
]),
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'ad_id',
//'advertiser_id',
//'publisher_id',
//'visitor_ip',
//'type_ad',
'impression',
'view',
'clicks',
//'placed_date',
//'cpc',
//'cpv',
'cpclick',
'cpview',
'totalccost',
//'cpi',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
But it is not giving me the desired output where am I going wrong how can i do this?
If you need the column only as display value in the gridview you can create a calculated column.
'cpview',
[
'label' => 'Totalcost',
'value' => function($model){
return $model->cpclick * $model->clicks;
}
],
Or else you can add at the start of your Adanalytics class
public $totalccost;
if you want to use the calculation anywhere you can do following.
in your model
public function getTotalcost()
{
return $this->clicks * $this->cpclick;
}
and you can label to this attribute
public function attributeLabels()
{
return [
...
'totalcost' => Yii::t('app', 'Total cost'),
];
}
in grid view column
...
'cpview',
'totalcost'
You can use this function anywhere as $model->totalcost
I have solved the problem by using yii2 db query which is like this way.
$subquery = Adanalytics::find()->
select('id,ad_id,date_event,max(cpc) cpclick,max(cpv) cpview,max(impression) impression,max(view) view,max(clicks) clicks,visitor_ip,publisher_id')->
from('ad_analytics')->
where(['publisher_id' => Yii::$app->user->identity->id ])->
groupBy('ad_id,date_event,visitor_ip');
$query=Adanalytics::find()->
select('ad_id,date_event,sum(cpclick) total_click_cost,sum(cpview) total_view_cost,sum(impression) total_impression,sum(view) total_views,sum(clicks) total_clicks,publisher_id')->
from(['t'=>$subquery])->
groupBy('t.ad_id,t.date_event');
And called the column in grid view.
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'ad_id',
'total_impression',
'total_views',
'total_clicks',
'total_click_cost',
'total_view_cost',
'date_event',
['class' => 'yii\grid\ActionColumn'],
],
Defined them in model before calling.
public $total_click_cost;
public $total_view_cost;
public $total_impression;
public $total_views;
public $total_clicks;
Related
To show my GridView I use this ActiveDataProvider:
public function search($params)
{
$query = PublicationsPublication::find()
->select(['eid', 'title', 'pubdate', 'citedby', "STRING_AGG(DISTINCT(CONCAT(author.authid, ' - ', authname)), ', ') AS authors"])
->joinWith('publicationsAuthor')
->groupBy(['eid','title','pubdate','citedby']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
...
}
I can't figure out how to use the column generated by the STRING_AGG() function in the Gridview.
Just in case is needed, the publicationsAuthor relation is coded this way:
public function getPublicationsAuthor() {
return $this->hasMany(PublicationsAuthor::className(), ['authid' => 'authid'])
->viaTable('publications.pub_author', ['pubid' => 'id']);
}
I need to use the STRING_AGG() function because I want to show many authors in one cell of the Gridview.
I tried to use the "authors" column in this way:
$gridColumns = [
[
'class' => 'kartik\grid\SerialColumn',
'width' => '20px',
],
'eid',
'title',
'pubdate',
'citedby',
'authors',
];
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => $gridColumns,
'pager' => [
'firstPageLabel' => 'First',
'lastPageLabel' => 'Last'
],
...
]);
But unfortunately it didn't work. In the Grid all the values are set to "not set". The query works great because I tested it in PgAdmin.
yii\data\ActiveDataProvider works with models so only fields defined by model are available by default. The easiest way to add field generated by some expression is to add public property with same name to your model like this:
class PublicationsPublication extends ActiveRecord
{
public $authors;
// ... other code in PublicationsPublication model ...
public function attributeLabels()
{
// You can also add label for new field
return [
'authors' => 'Authors',
// ... other labels ...
];
}
}
The public property $authors will be loaded with data from field authors in the result of your SQL query. Then you can use it in grid as any other field.
The other option is to use yii\data\SqlDataProvider instead of yii\data\ActiveDataProvider.
i'm developing a web application with Yii2 framework, and i'm facing a problem right now. I want to display the data from a many-to-many relation in a gridview and be able to filter from those fields later on.
I've read the official documentation here, some stackoverflow post like this and other resources but can't seem to get it to work. I have 3 tables: actividad, plan_actividad and circulo_icare, actividad is related to plan_actividad and circulo_icare is also related to it (plan_actividad is the junction table). So i have defined the following relations in my Actividad model:
class Actividad extends \yii\db\ActiveRecord
{
....
public function getPlanActividad()
{
return $this->hasMany(PlanActividad::classname(), ['act_id' => 'act_id']);
}
public function getCirculo()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'act_id'])->via('planActividad');
}
...
}
The in my view index.php i'm trying to show the values in a gridview like this:
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// 'act_id',
['attribute' => 'Codigo Evento', 'value' => 'act_numorden'],
['attribute' => 'Nombre Evento', 'value' => 'act_nombre'],
['attribute' => 'Fecha Evento', 'value' => 'act_fecha'],
['attribute' => 'Locacion', 'value' => 'locacion.loc_nombre'],
[
'attribute' => 'Circulo',
'value' => 'circulo.cirica_nombre',
],
['attribute' => 'Circulo id',
'value' => 'planActividad.cirica_id',
],
// 'act_horaini',
// 'act_horafin',
// 'act_idencuesta',
// 'act_vigencia:boolean',
// 'loc_id',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
The problem is, i can't get any values to show with the circulo relation, it always shows (not set). If i change hasMany in getPlanActividad() with hasOne() then it shows some values (only 2 of 11 it should, based on the cirica_id that exist on plan_actividad table) but these are not correct anyway. I know that i can filter for those fields later on in search view but i don't really understand why the relations doesn't work as i expected.
Any help would be greatly appreciated, let me know if more info is needed and thank you in advance.
Answering my own question (credits to softark from the yii official forums).
In order for the relation to work as expected, I had to change:
public function getCirculos()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'act_id'])->via('planActividad');
}
to
public function getCirculos()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'cirica_id'])->via('planActividad');
}
and use a callback function in the gridview to display the correct values, since a hasMany relation gives an array of models and not a single model. So I modified the gridview code to:
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
...
['attribute' => 'circulo',
'value' => function($model){
$items = [];
foreach($model->circulos as $circulo){
$items[] = $circulo->cirica_nombre;
}
return implode(', ', $items);
}],
...
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
This gives the expected results. You can then apply filter by the relation fields easily by adapting the search model.
I have a problem on getting all the selected values/data Yii2 Gridview using checkboxColumn.
I can only get one of the value in the grid using this code:
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
Need some suggestions on how can I get all the values in the grid...
Here is my Code Code snippet Controller/View:
Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');
print_r($selection);
}
View:
<?=Html::beginForm(['transjournal/bulk'],'post');?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'bordered'=>true,
'striped'=>true,
'condensed'=>true,
'hover'=>true,
'export' => false,
'showOnEmpty' => false,
'panel'=>[
'after'=>Html::submitButton('<i class="glyphicon glyphicon-plus"></i> Posted', ['class' => 'btn btn-success']),
],
'columns' => [
[
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
],
'item_id',
'description',
],
]);
?>
<?= Html::endForm();?>
Here is my attachment:
This is the GridView
This is the Result in the GridView (Selected Data only returns item_id)
How can I return both item_id and description?
Issue with your code 'checkboxOptions' =>, can you remove it?
<?=Html::beginForm(['controller/bulk'],'post');?>
<?=Html::dropDownList('action','',[''=>'Mark selected as: ','c'=>'Confirmed','nc'=>'No Confirmed'],['class'=>'dropdown',])?>
<?=Html::submitButton('Send', ['class' => 'btn btn-info',]);?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\CheckboxColumn'],
...
],
]); ?>
<?= Html::endForm();?>
In Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');//typecasting
foreach($selection as $id){
$model = Post::findOne((int)$id);//make a typecasting
//do your stuff
$model->save();
// or delete
}
}
basically, i am using yii's CheckboxColumn:
<?php
namespace common\grid;
class CheckboxColumn extends \yii\grid\CheckboxColumn {
public $headerOptions = ['class' => 'text-center', 'style' => 'width: 5em'];
public $contentOptions = ['class' => 'text-center'];
}
?>
then i wrote a jquery plugin for triggering operations with selected items, plus custom Actions and so on, here the relevant javascript code, where options.grid is the id/selector for your grid, e.g. '#grid':
var selection = [];
$(options.grid + ' input:checkbox[name="selection[]"]:checked').each(function() {
selection.push($(this).val());
});
so var selection contains an array with my item ids. length is:
selection.length
I add another table field in my view , but the search button disappeared , How can I retrieve this form button ?
SaleItems = And a table mysql database.
<?php
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'formatter' => ['class' => 'yii\i18n\Formatter','nullDisplay' => ''],
'columns' => [
['class' => 'yii\grid\SerialColumn'],
**[
'attribute' => 'Data',
'content' => function(SaleItems $model, $key, $index, $column) {
return date('d/m/Y', strtotime($model->sale->date));
},
'header' => 'DATA'
],**
]); ?>
</div>
The search field disappears because in not setted properly in searchModel ..
for this you must extend the related modelSeacrh adding the relation with the related model and the filter for the field you need ..
for this you must set in the base mode, the relation
public function getSale()
{
return $this->hasOne(Sale::className(), ['id' => 'sale_id']);
}
/* Getter for sale data */
public function getSaleData() {
return $this->sale->data;
}
then setting up the search model declaring
/* your calculated attribute */
public $date;
/* setup rules */
public function rules() {
return [
/* your other rules */
[['data'], 'safe']
];
}
and extending
public function search($params) {
adding proper sort, for data
$dataProvider->setSort([
'attributes' => [
.....
'data' => [
'asc' => ['tbl_sale.data' => SORT_ASC],
'desc' => ['tbl_sale.data' => SORT_DESC],
'label' => 'Data'
]
]
]);
proper relation
if (!($this->load($params) && $this->validate())) {
/**
* The following line will allow eager loading with country data
* to enable sorting by country on initial loading of the grid.
*/
$query->joinWith(['sale']);
return $dataProvider;
}
and proper filter condition
// filter by sale data
$query->joinWith(['sale' => function ($q) {
$q->where('sale.data = ' . $this->data . ' ');
}]);
Once you do al this the searchModel contain the information for filter and the search field is showed in gridview
What in this answer is just a list of suggestion
you can find detailed tutorial in this doc (see the scenario 2 and adapt to your need)
http://www.yiiframework.com/wiki/621/filter-sort-by-calculated-related-fields-in-gridview-yii-2-0/
I have a GridView which displays an employee's summary of his/her payslip. Here's a screenshot for more understanding:
Those highlighted columns come from a different model which is the User model while the rest come from the Payslip model.
How do I merge 2 models in one GridView? Because in GridView, it is more likely for you to have a single model to display data. But how about 2 models?
Here's a code in my Payslip model, note that getUser() is generated with gii since user_id is a foreign key in my payslip table:
public function getUser()
{
return $this->hasOne(User::className(), ['user_id' => 'user_id']);
}
public function getFirstName()
{
return $this->user ? $this->user->fname : 'First Name';
}
public function getLastName()
{
return $this->user ? $this->user->lname : 'Last Name';
}
The Payslip controller:
public function actionIndex()
{
$searchModel = new PayslipSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
And then the Payslip view:
<?php
echo GridView::widget([
'dataProvider' => $dataProvider,
//'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'payslip_id',
//'store_id',
'firstName',
'lastName',
'total_earnings',
'total_deduction',
'net_pay',
['class' => 'yii\grid\ActionColumn'],
],
]);
?>
BTW, in this example, I just created payslip #1 manually to give you a demo.
Additional info:
The logged in user is a BizAdmin user, and all of BizAdmin's staff users should be displayed in the payslip table (that table above) even if these staff users still don't have any payslip created for them. So by default, that table will be occupied already with staff users under the logged in BizAdmin user, and those staff users who still have no payslips created will be indicated "Create Payslip"
Here's an example in KashFlow:
Update view to:
<?php
echo GridView::widget([
'dataProvider' => $dataProvider,
//'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'payslip_id',
//'store_id',
['value' => function ($data) {return $data->getFirstName();}, 'label' => 'First Name'],
['value' => function ($data) {return $data->getLastName();}, 'label' => 'LastName'],
'total_earnings',
'total_deduction',
'net_pay',
['class' => 'yii\grid\ActionColumn'],
],
]);
?>
And in $searchModel->search add you relation, like that:
$query = Payslip::find()->with(['user']);
Read for data column - http://www.yiiframework.com/doc-2.0/guide-output-data-widgets.html#data-column