How to use Json for dataProvider Yii2 - json

Hot to use json for dataProvider for display data in Gridview Yii2?
Here is my Controller (Generate Code from Yii2 generator) code:
<?php
namespace app\controllers;
use Yii;
use app\models\Users;
use app\models\UsersSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* UsersController implements the CRUD actions for Users model.
*/
class UsersController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Users models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new UsersSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Users model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Users model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Users();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Users model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Users model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Users model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Users the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Users::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
And my gridview in index is like this:
<?php
use yii\helpers\Html;
use kartik\grid\GridView;
use yii\widgets\ActiveForm;
use yii\widgets\Pjax;
use yii\web\JsExpression;
/* #var $this yii\web\View */
/* #var $searchModel app\models\SalesOrderSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
?>
<div class="start-stock-index">
<div class="form-group">
<?= Html::a('Create Customer', ['create'], ['class' => 'btn btn-success']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
'dataProvider'=>$dataProvider,
'filterModel'=>$searchModel,
'showPageSummary'=>true,
'pjax'=>true,
'striped'=>true,
'hover'=>true,
'responsiveWrap' => false,
'panel'=>['type'=>'primary', 'heading'=>$partner_name],
'columns'=>[
[
'attribute' => 'cust_name',
'value' => 'cust_name',
'label' => 'Name',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
[
'attribute' => 'phone_number',
'value' => 'phone_number',
'label' => 'Phone Number',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
[
'attribute' => 'age_type',
'value' => 'ageType.age_name',
'label' => 'Age Category',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
['class' => 'kartik\grid\ActionColumn','template' => '{update} {delete}',],
],
]); ?>
<?php Pjax::end(); ?>
</div>
<?php
$script = <<< JS
JS;
$this->registerJs($script);
?>
What I want is show data from json so that it can be restful page. Thanks.

If you JSON structure is right for an arrayDataProvider
You could conver the JSON data in associative array the use the arrayDataprovider
you can use helper as http://www.yiiframework.com/doc-2.0/yii-helpers-json.html
http://www.yiiframework.com/doc-2.0/yii-helpers-basejson.html#decode()-detail
Json::decode($yourJSON);

Related

How to insert multiple times the value of an attribute in single table in yii2

I have a model named Taluka. I am supposed to select District and enter as many talukas for that specific district. Every thing is working, but when I enter multiple talukas, only last taluka is getting saved in database table. I have also tried the solution given in Yii2 Insert multiple records of a same table
But the error I received is "Call to a member function isAttributeRequired() on array"
Model:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "taluka".
*
*/
class Taluka extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public $talukas=[];
public static function tableName()
{
return 'taluka';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['DistrictId', 'Taluka'], 'required'],
[['DistrictId'], 'integer'],
[['talukas'], 'required'],
[['Taluka'], 'string', 'max' => 100],
[['DistrictId'], 'exist', 'skipOnError' => true, 'targetClass' => District::className(), 'targetAttribute' => ['DistrictId' => 'DistrictId']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'TalukaId' => 'Taluka ID',
'DistrictId' => 'District',
'talukas' => 'Taluka',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getDistrict()
{
return $this->hasOne(District::className(), ['DistrictId' => 'DistrictId']);
}
}
Controller:
<?php
namespace app\controllers;
use Yii;
use app\models\Taluka;
use app\models\TalukaSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use app\models\District;
use app\models\Model;
/**
* TalukaController implements the CRUD actions for Taluka model.
*/
class TalukaController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Taluka models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new TalukaSearch();
$dataProvider = $searchModel->search(Yii::$app->request-`>queryParams);`
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Taluka model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Taluka model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Taluka();
if ($model->load(Yii::$app->request->post()) ) {
echo $model->DistrictId;
$talukalist = $model->talukas;
if(is_array($talukalist))
{
foreach($talukalist as $v)
{
}
}
foreach($talukalist as $talukalist)
{
//echo $talukalist;
$model->Taluka = $talukalist;
echo $model->Taluka;
$model->save(false);
}
//return $this->redirect(['view', 'id' => $model->TalukaId]);
}
else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Taluka model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->TalukaId]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Taluka model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Taluka model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Taluka the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Taluka::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
View:
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use app\models\District;
use yii\helpers\ArrayHelper;
use unclead\multipleinput\MultipleInput;
/* #var $this yii\web\View */
/* #var $model app\models\Taluka */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="taluka-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form', 'layout' => 'horizontal',
'fieldConfig' => [
'template' => "{label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}",
'horizontalCssClasses' => [
'label' => 'col-sm-5',
//'offset' => 'col-sm-offset-2',
//'wrapper' => 'col-sm-7',
'error' => '',
'hint' => '',
],
],]);?>
<div class="panel panel-primary " >
<div class="panel panel-heading"><font size="3"><b>Taluka</b></font></div>
<div class="row">
<div class="col-sm-5">
<?= $form->field($model, 'DistrictId')->dropDownList(ArrayHelper::map(District::find()->all(),'DistrictId','District'), ['prompt' => 'Select District']) ?>
</div>
</div>
<div class="row">
<div class="col-sm-5">
<?php
echo $form->field($model, 'talukas')->widget(MultipleInput::className(), [
'max' => 500,
'min' => 1, // should be at least 2 rows
'allowEmptyList' => false,
//'enableGuessTitle' => true,
//'addButtonPosition' => MultipleInput::POS_HEADER // show add button in the header
]);
?>
</div>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
At first, let’s understand why you have an error "Call to a member function isAttributeRequired() on array". The reason is in rules method:
public function rules()
{
return [
[['DistrictId', 'Taluka'], 'required'],
[['DistrictId'], 'integer'],
[['talukas'], 'required'],// <-- This line causes an error. Reqired filed in ActiveRecord model could not be an array.
[['Taluka'], 'string', 'max' => 100],
[['DistrictId'], 'exist', 'skipOnError' => true, 'targetClass' => District::className(), 'targetAttribute' => ['DistrictId' => 'DistrictId']],
];
}
So it's better to remove [['talukas'], 'required'] from rules(). It is a custom field so it is not checked by ActiveRecord logic.
Also, there is a strange logic in actionCreate(). Keep in mind, that you've added a custom field to your model and don't fill Taluka, which is required, according to you model rules(). So you can't just load $_POST into model, and need to iterate through talukas to create a new record for each:
public function actionCreate()
{
$model = new Taluka();
if ($model->load(Yii::$app->request->post())) {
$talukaList = $model->talukas;
if (is_array($talukaList)) {
foreach ($talukaList as $taluka) {
$talukaRecord = new Taluka();
$talukaRecord->DistrictId = $model->DistrictId;
$talukaRecord->Taluka = $taluka;
$talukaRecord->save();
}
}
return $this->redirect(['view', 'id' => $talukaRecord->TalukaId]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
I assume, that TalukaId is an autoincrement primary key. After saving all records, it will redirect you to the last created taluka.

Insert multiple rows into table by checkboxcolumn in yii2

I have a table rawmaterial. The fields are - rmname, usedate, useqty, unitcost, productname, chargenumber. I've added a gridview (which comes from rmtemplate table) with a checkboxcolumn in the form. The gridview contains columns productname, rmname, qty, unitcost. How can I insert the checked rows along with usedate, chargenumber(which come from respective textboxes) in the table rawmaterial.
I've checked ActiveRecord batch insert (yii2) but not getting how to use it with checkbocolumn.
Checked How I can process a checkbox column from Yii2 gridview? - not quite sure with it.
Checked Yii2 How to properly create checkbox column in gridview for bulk actions? - I think it's not using activeform.
form.php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\grid\GridView;
use dosamigos\datepicker\DatePicker;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
use frontend\models\Rmtemplate;
/* #var $this yii\web\View */
/* #var $model frontend\models\Rawmaterial */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="rawmaterial-form">
<?php $form = ActiveForm::begin(); ?>
<div class="form-group">
<div class="col-xs-12 col-sm-12 col-lg-12">
<?= $form->field($model, 'usedate')->widget(
DatePicker::className(), [
// inline too, not bad
'inline' => false,
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'clientOptions' => [
'autoclose' => true,
'todayHighlight' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
</div>
<div class="col-xs-12 col-sm-12 col-lg-12">
<?= GridView::widget([
'dataProvider' => $dataProvider2,
'filterModel' => $searchModel2,
'columns' => [
['class' => 'kartik\grid\CheckboxColumn'],
//'id',
//'productname',
[
'attribute'=>'productname',
'filterType'=>GridView::FILTER_SELECT2,
'filter'=>ArrayHelper::map(Rmtemplate::find()->orderBy(['productname' => SORT_ASC])->asArray()->all(), 'productname', 'productname'),
'filterWidgetOptions'=>[
'pluginOptions'=>['allowClear'=>true],
],
'filterInputOptions'=>['placeholder'=>'Charge Name'],
],
'rmname',
'qty',
[
'attribute' => 'unitcost',
'value' => 'unitcost.unitcost',
],
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
</div>
<?= $form->field($model, 'chargenumber')->textInput()->hiddenInput()->label(false) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','name' => 'submit', 'value' => 'create_update']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
/* start getting the chargeno */
$script = <<<EOD
$(window).load(function(){
$.get('index.php?r=rmprod/rawmaterial/get-for-chargeno',{ orderid : 1 }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#rawmaterial-chargenumber').attr('value',data.chargeno);
}
);
});
EOD;
$this->registerJs($script);
/*end getting the chargeno */
?>
And it looks like below.
CreateAction looks like -
public function actionCreate()
{
$model = new Rawmaterial();
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
if (isset($_POST['submit'])) {
if ($_POST('submit') == 'create_update' ) {
// then perform the insert
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
}
} else {
// no insert but render for filter ..
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
}
Update
RawMaterialForm.php
<?php
namespace frontend\modules\rmprod\models;
use Yii;
/**
* This is the model class for table "rawmaterial".
*
* #property integer $id
* #property string $vname
* #property string $challan
* #property string $purchasedate
* #property string $purchaseqty
* #property string $rate
* #property string $rmname
* #property string $usedate
* #property string $useqty
* #property string $unitcost
* #property string $productname
* #property integer $chargenumber
*/
class RawMaterialForm extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'rawmaterial';
}
/**
* #inheritdoc
*/
// public function rules()
// {
// return [
// [['purchasedate', 'usedate'], 'safe'],
// [['chargenumber'], 'integer'],
// [['vname', 'productname'], 'string', 'max' => 40],
// [['challan'], 'string', 'max' => 20],
// [['purchaseqty', 'rmname', 'useqty'], 'string', 'max' => 50],
// [['rate', 'unitcost'], 'string', 'max' => 10],
// ];
// }
public function rules()
{
return [
[['usedate'], 'safe'],
[['chargenumber'], 'integer'],
[['productname'], 'string', 'max' => 40],
[['rmname', 'useqty'], 'string', 'max' => 50],
[['unitcost'], 'string', 'max' => 10],
[['rmtemplate_ids'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'vname' => 'Vname',
'challan' => 'Challan',
'purchasedate' => 'Purchasedate',
'purchaseqty' => 'Purchaseqty',
'rate' => 'Rate',
'rmname' => 'Rmname',
'usedate' => 'Usedate',
'useqty' => 'Useqty',
'unitcost' => 'Unitcost',
'productname' => 'Productname',
'chargenumber' => 'Chargenumber',
];
}
}
RawmaterialController
<?php
namespace frontend\modules\rmprod\controllers;
use Yii;
use frontend\models\Rawmaterial;
use frontend\modules\rmprod\models\RawmaterialSearch;
use frontend\modules\rmprod\models\RmtemplateSearch;
use frontend\modules\rmprod\models\RawMaterialForm;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\Json;
/**
* RawmaterialController implements the CRUD actions for Rawmaterial model.
*/
class RawmaterialController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Rawmaterial models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new RawmaterialSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
/**
* Displays a single Rawmaterial model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Rawmaterial model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new RawMaterialForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(
['create']
// redirect to where you want
);
}
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
/**
* Updates an existing Rawmaterial model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Rawmaterial model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
public function actionGetForChargeno($orderid)
{
$rates = Rawmaterial::find()->select('(max(chargenumber) + 1) as chargeno')->asArray()->one();
echo Json::encode($rates);
}
/**
* Finds the Rawmaterial model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Rawmaterial the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Rawmaterial::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function save()
{
try {
if ($this->validate()) {
// assuming Rmtemplate is the model used in RmtemplateSearch
$selectedRmtemplate = Rmtemplate::find()->where(['id' => $this->rmtemplate_ids]);
foreach ($selectedRmtemplate->each() as $rm) {
$rawMaterial = new Rawmaterial();
$rawMaterial->rmname = $rm->rmname;
$rawMaterial->usedate = $this->usedate;
$rawMaterial->useqty = $rm->qty;
$rawMaterial->unitcost = $rm->unitcost;
$rawMaterial->productname = $rm->productname;
$rawMaterial->chargenumber = $this->chargenumber;
if (!$rawMaterial->save()) {
throw new \Exception('Error while saving rawMaterial!');
}
}
return true;
}
} catch (\Exception $exc) {
\Yii::error($exc->getMessage());
}
return false;
}
}
Error
According to my understanding, you have to do two things.
Firstly, you have to grab all the checked rows data of the grid view as an array or object. You can see how to do that from Get Grid Data .
Secondly you have to change your create action for handling the data you fetch from that grid. You can take help from Batch Insert
Hope it helps...
Prepare additional model like RawMaterialForm with properties that will be taken from ActiveForm usedate, chargenumber and rmtemplate_ids. The last one is the array of GridView IDs. Remember to add rules() in the RawMaterialForm for the properties.
The view - just the GridView needs some tweaks. Extend the configuration for Checkbox column.
[
'class' => 'kartik\grid\CheckboxColumn',
'name' => 'RawMaterialForm[rmtemplate_ids]',
'checkboxOptions' => function ($model, $key, $index, $column) {
return ['value' => $model->id];
}
],
The action:
public function actionCreate()
{
$model = new RawMaterialForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(
// redirect to where you want
);
}
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
RawMaterialForm's save() method:
public function save()
{
try {
if ($this->validate()) {
// assuming Rmtemplate is the model used in RmtemplateSearch
$selectedRmtemplate = Rmtemplate::find()->where(['id' => $this->rmtemplate_ids]);
foreach ($selectedRmtemplate->each() as $rm) {
$rawMaterial = new Rawmaterial();
$rawMaterial->rmname = $rm->rmname;
$rawMaterial->usedate = $this->usedate;
$rawMaterial->useqty = $rm->qty;
$rawMaterial->unitcost = $rm->unitcost;
$rawMaterial->productname = $rm->productname;
$rawMaterial->chargenumber = $this->chargenumber;
if (!$rawMaterial->save()) {
throw new \Exception('Error while saving rawMaterial!');
}
}
return true;
}
} catch (\Exception $exc) {
\Yii::error($exc->getMessage());
}
return false;
}
This will copy every selected row into a new Rawmaterial row with additional inputs from ActiveForm.
In case of errors in $rawMaterial saving check $rawMaterial->errors property.
Fair warning - depending on the system performance this can be slow (or even fatal) in case of selecting many rows at once.

calculate average in yii2

I am making a cost accounting application.
I want to find the average price over 3 months.
The summary produced in Kartik GridView shows initial share price not the total.
this is my controller
<?php
namespace backend\controllers;
use Yii;
use backend\models\Triwulan;
use backend\models\TriwulanSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* TriwulanController implements the CRUD actions for Triwulan model.
*/
class TriwulanController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Triwulan models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new TriwulanSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Triwulan model.
* #param string $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Triwulan model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Triwulan();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->rm_code]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Triwulan model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param string $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->rm_code]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Triwulan model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param string $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Triwulan model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param string $id
* #return Triwulan the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Triwulan::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
this is my view
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use kartik\grid\GridView;
/* #var $this yii\web\View */
/* #var $model backend\models\Triwulan */
$this->title = $model->rm_code;
$this->params['breadcrumbs'][] = ['label' => 'Triwulans', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="triwulan-view">
<h1><?= Html::encode($this->title) ?></h1>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'rm_code',
'deskripsi_barang',
],
]) ?>
</div>
<?= GridView::widget([
'dataProvider'=>new yii\data\ActiveDataProvider([
'pagination'=>false,
'query'=>$model->getPenerimaans(),
]),
'columns'=>[
['class' => 'kartik\grid\SerialColumn'],
'rm_code',
'bulan',
// 'price',
[
'label' => 'Price',
//'attribute' => 'idDhs.idMatakuliah.jam',
'pageSummary' => true,
// 'pageSummary' => 'Total',
'value' => function ($model) {
if ($model)
return $model->price / 3;
}
],
// ['class' => 'kartik\grid\ActionColumn'],
// 'product',
// 'qty'
],
'showPageSummary' => true,
]) ?>
</div>
Correcting some syntax errors from scaisEdge's answer
public function actionIndex()
{
$searchModel = new TriwulanSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// calc the average
$myAverage = 0;
$myTot =0;
$myCnt = 0;
foreach ($dataProvider->models as $key => $value) {
$myTot += $value['price'];
$cnt++; // This should be $myCnt
}
if ($cnt>0){ // inside if use $myCnt
$myAverage = myTot/$myCont // here use $myTot/$myCnt
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
// render the avegare too
'myAverage' => $myAverage,
]);
}

Trying to get property of non-object in action column in yii2

I've customized the query in FrameSearch Model and build my query with findbysql. I'm also trying to customize the action column. My gridview looks fine except the action Column.
Getting error -
FrameSearch Model Code -
<?php
namespace frontend\modules\framestock\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\modules\framestock\models\Frame;
use frontend\modules\framestock\models\Poitemframe;
use yii\db\Query;
use yii\db\Command;
/**
* FrameSearch represents the model behind the search form about `frontend\modules\framestock\models\Frame`.
*/
class FrameSearch extends Frame
{
public $purchase;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['f_id'], 'integer'],
[['f_brand', 'f_name','purchase'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$subQuery1 = (new Query())->select(['poi_framename','sum(poi_qty) as purchased'])->from ('poitemframe')->join('LEFT JOIN','Frame','frame.f_name = poitemframe.poi_framename')->groupby('poi_framename');
$subQuery2 = (new Query())->select(['o_frame','count(o_frame) as sold'])->from ('orders')->join('LEFT JOIN','Frame','frame.f_name = orders.o_frame')->groupby('o_frame');
$query = (new Query())->select(['f_brand','f_name','COALESCE(pt.purchased,0)as purchased' , 'COALESCE(st.sold,0) as sold', '(COALESCE(pt.purchased,0) - COALESCE(st.sold,0)) as stock'])->from ('frame')->leftJoin(['pt' => $subQuery1],'pt.poi_framename = frame.f_name')->leftJoin(['st' => $subQuery2],'st.o_frame = frame.f_name');
// ->joinWith(['purchase']);
// $items = $query
// ->select([
// 'f_brand',
// 'f_name',
// 'sum(poitemframe.poi_qty) as purchased',
// ])
// //->where(['stock.product_id'=>3])
// ->groupBy('f_name')
// ->all();
// 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([
'f_id' => $this->f_id,
]);
$query->andFilterWhere(['like', 'f_brand', $this->f_brand])
->andFilterWhere(['like', 'f_name', $this->f_name]);
return $dataProvider;
}
}
index.php
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\db\Query;
use yii\db\Command;
/* #var $this yii\web\View */
/* #var $searchModel frontend\modules\framestock\models\FrameSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Frames';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="frame-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'f_brand',
'f_name',
'purchased',
'sold',
'stock',
[
'class' => 'yii\grid\ActionColumn',
'template' => '{ledger}',
'buttons' => [
'ledger' => function ($url, $model) {
return Html::a(
'<span class="glyphicon glyphicon-eye-open"></span>',
['/frame/ledger', 'f_name' => $model->f_name],
[
'title' => 'Ledger',
'data-pjax' => '0',
]
);
},
],
],
],
]); ?>
</div>
update
After adding exit;
Please tell me how to resolve this. I want to get the f_name from the action column button which I'll pass to another page to filter a grid.
I usually recommend to use ArrayHelper::getValue .
For example:
ArrayHelper::getValue($model, 'f_name')
will work when $model is some object (Model or ActiveRecord), array or empty (=null).
Moreover, it has 3nd argument for default value:
ArrayHelper::getValue($model, 'f_name', 'value that returned when attribute not found in $model')

Data is not populating in second level kartik depDrop in yii2. Gettin 0,1,2,3,4

When I'm selecting First Category - I can see the data in firebug that should populate in the secon level but it's instead populating 0,1,2,3,4 and I'm unable to select it.
My _form is
<?php
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use yii\web\View;
use frontend\assets\XyzAsset;
use yii\helpers\ArrayHelper;
use dosamigos\datepicker\DatePicker;
use kartik\select2\Select2;
use frontend\modules\production\models\Productbatch;
use frontend\modules\production\models\Productnames;
use kartik\depdrop\DepDrop;
use yii\helpers\Json;
//XyzAsset::register($this);
/* #var $this yii\web\View */
/* #var $model frontend\modules\production\models\Production */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="production-form">
<?php $form = ActiveForm::begin(); ?>
<!--<?= Html::a('Select Product', ['/production/productbatch/index'], ['class'=>'btn btn-primary']) ?> -->
<?= $form->field($model, 'productiondate')->widget(
DatePicker::className(), [
// inline too, not bad
'inline' => false,
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'clientOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
<!-- echo CHtml::button("(+)",array('title'=>"Select Product",'onclick'=>'js:selectproductforproduction();')); -->
<?= $form->field($model, 'productname')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Productnames::find()->all(),'productnames_productname','productnames_productname'),
'language' => 'en',
'options' => ['placeholder' => 'Select Product Name', 'id' => 'cat-id'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
<?= $form->field($model, 'batchno')->widget(DepDrop::classname(), [
'options'=>['id'=>'subcat-id'],
'pluginOptions'=>[
'depends'=>['cat-id'],
'placeholder'=>'Select BatchNo',
'url'=>Url::to(['/production/productbatch/subcat'])
]
]); ?>
<?= $form->field($model, 'prodqty')->textInput() ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Controller -
<?php
namespace frontend\modules\production\controllers;
use Yii;
use frontend\modules\production\models\Productbatch;
use frontend\modules\production\models\ProductbatchSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\Json;
/**
* ProductbatchController implements the CRUD actions for Productbatch model.
*/
class ProductbatchController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
/**
* Lists all Productbatch models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new ProductbatchSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Productbatch model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Productbatch model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Productbatch();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->itemid]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Productbatch model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->itemid]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Productbatch model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
public function actionSubcat() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = Productbatch::getBatchNo($cat_id);
// the getSubCatList function will query the database based on the
// cat_id and return an array like below:
// [
// ['id'=>'<sub-cat-id-1>', 'name'=>'<sub-cat-name1>'],
// ['id'=>'<sub-cat_id_2>', 'name'=>'<sub-cat-name2>']
// ]
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
/**
* Finds the Productbatch model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Productbatch the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Productbatch::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
Model
<?php
namespace frontend\modules\production\models;
use Yii;
/**
* This is the model class for table "productbatch".
*
* #property integer $itemid
* #property string $productname
* #property string $batchno
* #property string $mfgdate
* #property string $expdate
* #property double $mrp
* #property double $rate
*
* #property Productnames $productname0
*/
class Productbatch extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'productbatch';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['batchno'], 'string'],
[['mfgdate', 'expdate'], 'safe'],
[['mrp', 'rate'], 'number'],
[['productname'], 'string', 'max' => 25]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'itemid' => 'Itemid',
'productname' => 'Productname',
'batchno' => 'Batchno',
'mfgdate' => 'Mfgdate',
'expdate' => 'Expdate',
'mrp' => 'Mrp',
'rate' => 'Rate',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getProductname0()
{
return $this->hasOne(Productnames::className(), ['productnames_productname' => 'productname']);
}
public static function getBatchNo($cat_id)
{
$data = static::find()->where(['productname'=>$cat_id])->select(['batchno'])->asArray()->all();
$value = (count($data) == 0) ? ['' => ''] : $data;
return $value;
}
}
The output looks like -