Undefined variable: yii2 - yii2

Getting error when I am trying to create dynamic form in using yii2-dynamicform. at the time of create method it is working fine but at the time of update showing the error. I have two tables one is
1.vendors &
2.vendors_more_categories
Relation is 1-* between vendors & vendors_more_categories I just refereed https://github.com/wbraganca/yii2-dynamicform this link.
<?php
namespace app\controllers;
namespace backend\controllers;
use Yii;
use app\models\Vendors;
use app\models\VendorsSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\web\UploadedFile;
use yii\filters\AccessControl;
use app\models\VendorsMoreCategories;
use backend\models\Model;
use yii\web\Response;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
/**
* VendorsController implements the CRUD actions for Vendors model.
*/
class VendorsController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['index','create', 'update', 'delete'],
'rules' => [
[
'actions' => ['index','create', 'update', 'delete'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
/**
* Lists all Vendors models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new VendorsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Vendors model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Vendors model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Vendors();
$modelsVendorsMoreCategories = [new VendorsMoreCategories];
if($model->load(Yii::$app->request->post())){
$modelsVendorsMoreCategories = Model::createMultiple(VendorsMoreCategories::classname());
Model::loadMultiple($modelsVendorsMoreCategories, Yii::$app->request->post());
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsVendorsMoreCategories) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsVendorsMoreCategories as $modelVendorsMoreCategories) {
$modelVendorsMoreCategories->vmc_ven_id = $model->ven_id;
if (! ($flag = $modelVendorsMoreCategories->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
$model->file = UploadedFile::getInstance($model, 'file');
$save_file = '';
if($model->file){
$imagename = Vendors::find()->orderBy('ven_id DESC')->one();
$imagename=$imagename->ven_id+1;
$imagepath = 'images/imgvendors/'; // Create folder under web/uploads/logo
$model->ven_business_logo = $imagepath.$imagename.'.'.$model->file->extension;
$save_file = 1;
}
if ($model->save(false)) {
if($save_file){
$model->file->saveAs($model->ven_business_logo);
}
return $this->redirect(['view', 'id' => $model->ven_id]);
}
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}else {
return $this->render('create', [
'model' => $model,
'modelsVendorsMoreCategories' => (empty($modelsVendorsMoreCategories)) ? [new VendorsMoreCategories] : $modelsVendorsMoreCategories
]);
}
}
/**
* Updates an existing Vendors 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);
//print_r($model->attributes);
$modelsVendorsMoreCategories = $model->ven_id;
if($model->load(Yii::$app->request->post())){
$oldIDs = ArrayHelper::map($modelsVendorsMoreCategories, 'id', 'id');
$modelsVendorsMoreCategories = Model::createMultiple(VendorsMoreCategories::classname(), $modelsVendorsMoreCategories);
Model::loadMultiple($modelsVendorsMoreCategories, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsVendorsMoreCategories, 'id', 'id')));
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsVendorsMoreCategories) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
Address::deleteAll(['id' => $deletedIDs]);
}
foreach ($modelsVendorsMoreCategories as $modelVendorsMoreCategories) {
$modelVendorsMoreCategories->vmc_ven_id = $model->ven_id;
if (! ($flag = $modelVendorsMoreCategories->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
$model->file = UploadedFile::getInstance($model, 'file');
$save_file = '';
if($model->file){
$imagepath = 'images/imgvendors/'; // Create folder under web/uploads/logo
$model->ven_business_logo = $imagepath.$model->ven_id.'.'.$model->file->extension;
$save_file = 1;
}
if ($model->save(false)) {
if($save_file){
$model->file->saveAs($model->ven_business_logo);
}
return $this->redirect(['view', 'id' => $model->ven_id]);
}
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}else {
return $this->render('update', [
'model' => $model,
'modelsVendorsMoreCategories' => (empty($modelsVendorsMoreCategories)) ? [new VendorsMoreCategories] : $modelsVendorsMoreCategories
]);
}
}
/**
* Deletes an existing Vendors 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 Vendors model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Vendors the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Vendors::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
//Function used for deleting the images
public function actionDeleteimg($id, $field)
{
$img = $this->findModel($id)->$field;
if($img){
if (!unlink($img)) {
return false;
}
}
$img = $this->findModel($id);
$img->$field = NULL;
$img->update();
return $this->redirect(['update', 'id' => $id]);
}
//Function used for getting more sub categories for vendor
public function actionGetSubCategories()
{
$mbcid=$_GET['ven_main_category_id'];
$sbcid=$_GET['ven_sub_category_id'];
echo $mbcid;
}
public function actionLists($id)
{
$countVendors = Vendors::find()->where(['ven_contact_person_id' => $id])->count();
$vendors = Vendors::find()->where(['ven_contact_person_id' => $id])->all();
if ($countVendors > 0) {
foreach ($vendors as $vendor) {
echo "<option value='" . $vendor->ven_id . "'>" . $vendor->ven_company_name . "</option>";
}
} else {
echo "<option></option>";
}
}
}

You accessing modelsVendorsMoreCategories[0] (as an element of an array )
'model'=> $modelsVendorsMoreCategories[0],
in your DinamicForm widget but when you update the model you pass as $modelsVendorsMoreCategories this value
$modelsVendorsMoreCategories = $model->ven_id;
(don't seems an array, you must be sure this object contain an array with a proper element in 0 index))
'modelsVendorsMoreCategories' => (empty($modelsVendorsMoreCategories)) ?
[new VendorsMoreCategories] : $modelsVendorsMoreCategories
]);

$modelsVendorsMoreCategories should contain the VendorsMoreCategories model in actionUpdate method. In this code ($modelsVendorsMoreCategories = $model->ven_id) $modelsVendorsMoreCategories contains $model->ven_id. It is an integer value, not the VendorsMoreCategories object.
The Vendors model should contain a relation on the VendorsMoreCategories model:
class Vendors extends \yii\db\ActiveRecord
{
....
public function getVendorsMoreCategories()
{
return $this->hasMany(VendorsMoreCategories::className(), 'vendor_id'=>'id']);
}
}
And then, you should use that relation in your actionUpdate method:
$model = $this->findModel($id);
$modelsVendorsMoreCategories = $model->vendorsMoreCategories;
if(!$modelsVendorsMoreCategories) {
$modelsVendorsMoreCategories = [new VendorsMoreCategories];
}

In your actionUpdate you have:
$modelsVendorsMoreCategories = $model->ven_id;
But you should have:
$modelsVendorsMoreCategories = $model->nameOfMyRelation;
To get what's the real name, go in your $model, and look for something like:
/**
* #return \yii\db\ActiveQuery
*/
public function getNameOfMyRelation()
{
return $this->hasMany(VendorsMoreCategories::className(), ['ven_id' => 'id']);
}
If you don't have any function making the relation of this two tables, write one. If you having trouble doing that, you can always use the gii's model generator and check the Vendors model (you dont need to replace it, just preview the code).

Check your create.php file in view folder, pass required variable on
_form.php file from here as:-
<?= $this->render('_form', [
'model' => $model,
'modelsAddress' => $modelsAddress,
]) ?>

Check Your create file in view folder:
Controller:
Controller pass the parameter into create.php
return $this->render('create', [
'model' => $model,
'modelsVendorsMoreCategories' => (empty($modelsVendorsMoreCategories)) ? [new VendorsMoreCategories] : $modelsVendorsMoreCategories
]);
View:create.php
If You miss the parameter: 'modelsVendorsMoreCategories' =>$modelsVendorsMoreCategories.
It shows the Undefined variable error in _form.php page.
<?= $this->render('_form', [
'model' => $model,
'modelsVendorsMoreCategories' =>$modelsVendorsMoreCategories
])?>
View:_form.php
$modelsVendorsMoreCategories[0];
the paramater not passing before now it passing.

Related

Many To Many relations Yii2

I need help with this code, I'm new to Yii2.
I'm building a sample project to start, and I don't know why my code gets the right result but doesn't save the ids I need into the many-to-many table for the relationship.
I started from this sample in the wiki: https://www.yiiframework.com/wiki/708/book-has-author-many-to-many-relations-using-kartikselect2
My Model
public function rules()
{
return [
[['anno', 'durata', 'flagdelete', 'categoriaid'], 'integer'],
[['titolo', 'riassunto', 'regista', 'descrizione'], 'string', 'max' => 50],
[['attoriIds'], 'safe'],
];
}
public function attributeLabels()
{
return [
'titolo' => 'Titolo',
'anno' => 'Anno',
'durata' => 'Durata',
'riassunto' => 'Riassunto',
'regista' => 'Regista',
'descrizione' => 'Descrizione',
'categoriaid' => 'Categoria',
'nome' => 'Attori',
];
}
/**
* #var array
*/
public $attoriIds = [];
public function getdropAttori()
{
$data = Attori::find()->asArray()->all();
return ArrayHelper::map($data, 'id', 'nome');
}
/**
* #return mixed
*/
public function getAttoriIds()
{
return $this->attoriIds;
}
/**
* #param $attoriIds
*/
public function setAttoriIds($attoriIds)
{
$this->attoriIds = \yii\helpers\ArrayHelper::getColumn(
$this->getAttdvd()->asArray()->all(),
'attori_id'
);
}
/**
* #param $insert
* #param $changedAttributes
*/
public function afterSave($insert, $changedAttributes)
{
$actualAttoris = [];
$attoriExists = 0;
if (($actualAttoris = Attdvd::find()->andWhere(
"dvd_id = $this->id"
)->asArray()->all()) !== null
) {
$actualAttoris = ArrayHelper::getColumn($actualAttoris, 'attori_id');
$attoriExists = 1;
}
if (!empty($this->despIds)) {
foreach ($this->despIds as $id) {
$actualAttoris = array_diff($actualAttoris, [$id]);
$r = new Attdvd();
$r->dvd_id = $this->id;
$r->attori_id = $id;
$r->save();
}
}
if ($attoriExists == 1) {
foreach ($actualAttoris as $remove) {
$r = Attdvd::findOne(
['attori_id' => $remove, 'dvd_id' => $this->id]
);
$r->delete();
}
}
parent::afterSave($insert, $changedAttributes);
}
/**
* #return mixed
*/
public function getAttdvd()
{
return $this->hasMany(Attori::className(), ['id' => 'attori_id'])->viaTable(
'attdvd', ['dvd_id' => 'id']
);
}
My Controller
public function actionCreate()
{
$model = new Dvd();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
//i think the problem is the line below
$model->attoriIds = $model->AttoriIds;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
My form (that work properly):
<?= $form->field($model, 'AttoriIds')->widget(Select2::classname(), ['data'=>$model->dropAttori, 'options' => ['multiple' => true, 'placeholder' => 'Seleziona attori']])->label('Attori') ?>
It's bad way because the making of that code in multiple models will make models dirtier. The better way is usage of a universal component that can manage relations in your models. For example yii2-many-to-many-behavior

Yii2, how to use or operator in rest request

I am trying to use or operator in my rest request Yii2 but I cannot succeed.
Everytime I have this error :
[
{
"field": "filter",
"message": "Operator \"or\" requires multiple operands."
}
]
I tested several things but nothing works.
I want to filter
statut=0 or statut=1
Do you know or I can do it ?
I tried to
http://url/api/tickets/gestions?filter[or][statut][statut]=[0,1]
But it does not work
Here's the method within controller that manage this request :
public function actionIndex()
{
return ActionsHelper::actionIndex(
$this->modelClass,
$this->modelClass . 'Search'
);
}
$this->modelClass is defined above and is equal to 'api\modules\tickets\models\TicketGestion';
Here is ActionsHelper::actionIndex
public function actionIndex($model, $searchModel = null, $moreFilter = null,
$pagination = false)
{
$filterCondition = null;
if ($searchModel) {
$filter = new ActiveDataFilter([
'searchModel' => $searchModel
]);
if ($filter->load(\Yii::$app->request->get())) {
$filterCondition = $filter->build();
if ($filterCondition === false) {
return $filter;
}
}
}
$query = $model::find();
if ($filterCondition !== null) {
$query->andWhere($filterCondition);
}
if ($moreFilter !== null) {
$query->andWhere($moreFilter);
}
if ($pagination !== false) {
$pagination = [
'pageSize' => 100
];
}
return new ActiveDataProvider([
'query' => $query,
'pagination' => $pagination
]);
}
Here's the search model, generated by Gii
<?php
namespace api\modules\tickets\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use api\modules\tickets\models\TicketGestion;
/**
* TicketGestionSearch represents the model behind the search form of `api\modules\tickets\models\TicketGestion`.
*/
class TicketGestionSearch extends TicketGestion
{
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['id', 'priorite', 'quicree', 'quirea', 'statut', 'recurrentid', 'typerea', 'client'], 'integer'],
[['dispatch', 'service', 'type', 'sujet', 'datecrea', 'dateecheance', 'daterea'], 'safe'],
[['duree'], 'number'],
];
}
/**
* {#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)
{
$query = TicketGestion::find();
// 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;
}
if ($this->dispatch == 'null') {
$this->dispatch = 1;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'priorite' => $this->priorite,
'quicree' => $this->quicree,
'quirea' => $this->quirea,
'datecrea' => $this->datecrea,
'dateecheance' => $this->dateecheance,
'daterea' => $this->daterea,
'duree' => $this->duree,
'statut' => $this->statut,
'recurrentid' => $this->recurrentid,
'typerea' => $this->typerea,
'client' => $this->client,
]);
$query->andFilterWhere(['like', 'service', $this->service])
->andFilterWhere(['like', 'type', $this->type])
->andFilterWhere(['like', 'sujet', $this->sujet])
->andFilterWhere(['likes', 'dispatch', $this->dispatch]);
return $dataProvider;
}
}
You were on a right track, using ActiveDataFilter, but building arrays from get is done like this (example is from my controller):
http://localhost/ntb/web/index.php?r=assembly%2Findex&filter[or][0][status]=1004&filter[or][1][status]=1005&page=1&per-page=10
so for your example it should be like this:
http://url/api/tickets/gestions?filter[or][0][statut]=0&filter[or][1][statut]=1
This was the way to build a working 'or' filter for me.

Use closures in Yii2 ArrayDataProvider

In an ActiveDataProvider you can use closures as values, like:
$dataprovider = new ArrayDataProvider([
'allModels' => $array
]);
$gridColumns = [
'attrib_1',
[
'attribute' => 'attrib_2',
'label' => 'Label_2',
'value' => function($model) {
return Html::encode($model->value_2);
}
],
'attrib_3'
];
echo GridView::widget([
'dataProvider'=> $dataprovider,
'columns' => $gridColumns
]);
Is it possible to do the same or something like this, in an ArrayDataProvider?
Yes. Only difference is that $model is not an object but array so:
'value' => function($model) {
return Html::encode($model['value_2']);
}
For this purpose, I have created an extended version of ActiveDataProvider, that for each model got from provider I call a callback.
This is the custom ActiveDataProvider, put in common\components namespace in this case.
<?php
namespace common\components;
class CustomActiveDataProvider extends \yii\data\ActiveDataProvider
{
public $formatModelOutput = null;
public function getModels()
{
$inputModels = parent::getModels();
$outputModels = [];
if($this->formatModelOutput != null)
{
for($k=0;$k<count($inputModels);$k++)
{
$outputModels[] = call_user_func( $this->formatModelOutput, $k , $inputModels[$k]);
}
}
else
{
$outputModels = $inputModels;
}
return $outputModels;
}
}
This is the action in controller that uses it. For reusability, I call a model method instead calling a clousure, but you can call also a clousure.
public function actionIndex()
{
$query = Model::find();
$dataProvider = new \common\components\CustomActiveDataProvider([
'query' => $query,
'pagination' => ['pageSize' => null],
'formatModelOutput' => function($id, $model) {
return $model->dataModelPerActiveProvider;
}
]);
return $dataProvider;
}
At last, this is the method getDataModelPerActiveProvider in model:
public function getDataModelPerActiveProvider()
{
$this->id = 1;
// here you can customize other fields
// OR you can also return a custom array, for example:
// return ['field1' => 'test', 'field2' => 'foo', 'field3' => $this->id];
return $this;
}

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,
]);
}