Trying to get property of non-object in kartik expandrow in yii2 - yii2

I'm trying to use kartik expandrow.
In the first level query in PartiesSearch Model is-
$query = (new Query())->select(['district'])->from('districts');
In the second level query in ExpartiesSearch Model is -
$query = (new Query())->select(['parties_district','parties_partyname'])->from('parties');
The code for expandrow in index.php is -
[
//['class' => 'yii\grid\SerialColumn'],
'class' => 'kartik\grid\ExpandRowColumn',
'value' => function($model, $key, $index, $column){
return GridView::ROW_COLLAPSED;
},
'detail' => function($model, $key, $index, $column){
$searchModel = new ExpartiesSearch();
$searchModel-> parties_district = $model-> district;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return Yii::$app->controller->renderPartial('_exparties', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
},
],
I'm getting error -
Trying to get property of non-object
The highlighted error line is -
$searchModel-> parties_district = $model-> district;
The same piece of code works fine if I change the query in PartiesSearch Model to
$sql = 'select district from districts';
$query = Districts::findBySql($sql);
But, I have to write the query in that particular format (Derived from Query Builder) only. Please help.

In my test this:
$query = (new Query())->select(['district'])->from('districts');
will return you array of arrays. You need to use $model['district'] in this case.
[
//['class' => 'yii\grid\SerialColumn'],
'class' => 'kartik\grid\ExpandRowColumn',
'value' => function ($model, $key, $index, $column) {
return GridView::ROW_COLLAPSED;
},
'detail' => function ($model, $key, $index, $column) {
$searchModel = new ExpartiesSearch();
$searchModel->parties_district = $model['district'];
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return Yii::$app->controller->renderPartial('_exparties', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
},
Try to use xdebug to see what exactly in your $model

Related

Yii2 insert data from CheckBoxList

In my Form:
<?= GridView::widget([
'id' => 'griditems',
'dataProvider' => $dataProvider,
'columns' => [
'receiver_name',
'receiver_phone',
'item_price',
'shipment_price',
['class' => 'yii\grid\CheckboxColumn'],
],
]); ?>
In my Controller:
public function actionCreate()
{
$model = new Package();
$searchModel = new ShipmentSearch();
$searchModel->shipment_position=1; // الشحنه في مقر الشركة
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if ($model->loadAll(Yii::$app->request->post())){
$select = Yii::$app->request->post('selection');
foreach($select as $id){
$shipment= shipment::findOne((int)$id);
$model->company_id=1;
$model->shipment_id=$shipment->id;
$model->send_from=$shipment->send_from;
$model->send_to=$shipment->send_to;
$model->save(false);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'dataProvider'=>$dataProvider,
]);
}
}
I just try this way to insert data as above its works but the data inserted just last one or last CheckBox from the list. I tried to print the id that in foreach and there is more than one id.
That is beacuse you're reusing the same instace for each save() inside of foreach, so you're overwriting the same model over and over. You need to place $model = new Package() inside of foreach:
foreach($select as $id){
$shipment= shipment::findOne((int)$id);
$model = new Package();
$model->company_id=1;
$model->shipment_id=$shipment->id;
$model->send_from=$shipment->send_from;
$model->send_to=$shipment->send_to;
$model->save(false);
}

Yii2- How to restrict a user from viewing others data in index page

I am working on yii2 in my project, I have users and their roles. Each role is given access to a Module and a Sub Menu. There is a sub-menu named SIM List in which all the SIM records can be viewed. There is a field named issued_to which tells us that which SIM has been issued to which user.
Unless a SIM is issued to any user, the issued_to field will remain empty. Once issued the name of the user will appear on the SIM List.
Now I want to manage it in such a way that only a specific user can see the list. For example 5 Sims have been issued to a user named U. Now the user U should only see that SIM records which are issued to him, otherwise the list should be empty.
In my Index controller I am getting issued_to field name which is empty by default.
public function actionIndex()
{
$searchModel = new SimsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
By doing like below I can get issued_to user id
$model = $dataProvider->getModels()[0];
$user_id = $model['issued_to'];
var_dump($user_id);
exit();
Now in this controller, I want to add a check of user_id which gives me only the records which are of that specific user.
Index View
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'imsi',
'sim_number',
'operator_name',
'data_details',
'sms_details',
'monthly_bill',
//'created_by',
[
'label' => 'Created By',
'value' => function ($data) {
if (is_object($data))
return $data->created->name;
return ' - ';
},
//'filter' => Html::activeDropDownList($searchModel, 'created_by', \app\models\User::toArrayList(), ['prompt' => "Created By", 'class' => 'form-control']),
],
'created_at',
// 'updated_at',
'status',
// 'updated_by',
//'sim_stauts',
[
'label'=>'SIM Status',
'value'=>function($a){
return $a->getStatusvalue();
}
],
//'issued_to',
[
'label' => 'Issued To',
'value' => function ($d) {
if(is_object($d->user))
//return $d->user->name;
return $d->issued_to == '' ? '' : $d->user->username;
return ' - ';
// return $d->user->name;
},
'filter' => Html::activeDropDownList($searchModel, 'issued_to', \app\models\User::toArrayList(), ['prompt' => "Users", 'class' => 'form-control']),
],
//'returned_by',
[
'label' => 'Returned By',
'value' => function ($d) {
if(is_object($d->user2))
//return $d->user->name;
return $d->returned_by == '' ? '' : $d->user->username;
return ' - ';
// return $d->user->name;
},
'filter' => Html::activeDropDownList($searchModel, 'returned_by', \app\models\User::toArrayList(), ['prompt' => "Users", 'class' => 'form-control']),
],
'historic',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Update 1
My search model is below
public function search($params)
{
$query = Sims::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;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'created_by' => $this->created_by,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'updated_by' => $this->updated_by,
'sim_stauts' => $this->sim_stauts,
'issued_to' => $this->issued_to,
'returned_by' => $this->returned_by,
'historic' => $this->historic,
]);
$query->andFilterWhere(['like', 'imsi', $this->imsi])
->andFilterWhere(['like', 'sim_number', $this->sim_number])
->andFilterWhere(['like', 'operator_name', $this->operator_name])
->andFilterWhere(['like', 'data_details', $this->data_details])
->andFilterWhere(['like', 'sms_details', $this->sms_details])
->andFilterWhere(['like', 'monthly_bill', $this->monthly_bill])
->andFilterWhere(['like', 'status', $this->status]);
return $dataProvider;
}
How can I achieve it? Any help would be highly appreciated.
As per your description, you have the user_id saved inside the issued_to field and you need to only fetch the results that have the current logged in user_id saved in the field issued_to.
I assume that your search in the grid view is visible to only logged-in users.
You should set the issued_to param manually by first getting the queryParams array from the request object Yii::$app->request->queryParams; which has the array in the same format as the POST has i.e ['ModelName']['field_name'] so you need to infact set the issued_to as
$arrayParams['SimSearch']['issued_to']=Yii:$app->user->id;
Your actionIndex should look like below
public function actionIndex()
{
$searchModel = new SimsSearch();
$queryParams=Yii::$app->request->queryParams;
//check if user or one of the managers
$isAdmin=in_array(Yii::$app->user->identity->user_role,[1,6]);
//set params if normal user
if(!$isAdmin){
$queryParams['SimsSearch']['issued_to']=Yii::$app->user->id;
}
$dataProvider = $searchModel->search($queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
Hope this helps you out.

Yii2 Undefined index

My controller:
$params = Yii::$app->request->queryParams;
$query4 = (new \yii\db\Query())
->select(['monthsubmit', 'modeler'])
->from('sku3d')
->groupBy(['monthsubmit', 'modeler'])
->orderBy(['monthsubmit'=>SORT_DESC]);
$query4->andFilterWhere(['like', 'monthsubmit', $params['monthsubmit']])
->andFilterWhere(['like', 'modeler', $params['modeler']]);
$dataProvider4 = new ActiveDataProvider([
'query' => $query4,
]);
MY view:
<?php echo GridView::widget([
'dataProvider' => $dataProvider4,
'filterModel' => true,
'pjax'=>true,
'panel' => [
'type' => GridView::TYPE_PRIMARY,
'heading' => '<h3 class="panel-title"><i class="glyphicon glyphicon-user"></i>Submitted SKU by Month</h3>',
],
'columns' => [
// 'monthsubmit',
[
'attribute'=>'monthsubmit',
'filter' => Html::input('string', 'monthsubmit')
'width'=>'310px',
'group'=>true, // enable grouping
],
[
'attribute'=>'modeler',
'width'=>'180px',
'filter' => Html::input('string', 'modeler')
'group'=>true, // enable grouping
],
]
]);
?>
I have created sqlDataProvider in my controller and its working. My problem is when i try to create a filter option since im not using the search model for my gridview, it return error Undefined index: monthsubmit.
Please tell me where I'm wrong.
Thank you.
In your controller, you should do as this
$modeler = Yii::$app->request->get('modeler');
$monthsubmit = Yii::$app->request->get('monthsubmit');
$query4 = (new \yii\db\Query())
->select(['monthsubmit', 'modeler'])
->from('sku3d')
->groupBy(['monthsubmit', 'modeler'])
->orderBy(['monthsubmit'=>SORT_DESC]);
$query4->andFilterWhere(['like', 'monthsubmit', $monthsubmit])
->andFilterWhere(['like', 'modeler', $modeler]);
$dataProvider4 = new ActiveDataProvider([
'query' => $query4,
]);

Show only 5 item in yii2 List view

In my yii2 application list view need to show only 5 product limit.
This my View page
<?= ListView::widget( [
'dataProvider' => $dataProvider,
'itemView' => '_item',
'summary' => '',
] ); ?>
and this my controller
$searchModel = new HorseAdsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
this my Model search Function
public function search($params)
{
$query = HorseAds::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'product_id' => $this->product_id,
'producttype' => $this->producttype,
'productname' => $this->productname,
]);
return $dataProvider;
}
Please help me solve this, thanks
Try somthing like this: idea is that set limit with find and set pagination to false
public function search($params)
{
$query = HorseAds::find()->limit(5);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'product_id' => $this->product_id,
'producttype' => $this->producttype,
'productname' => $this->productname,
]);
return $dataProvider;
}

Set enablePushState = false on specific urls inside Pjax container (Yii2)

I need pjax to work on change status click and it's working fine but don't want it to change the URL as well. Below is the code:
<?php Pjax::begin(['id'=>'pjax-container-agency-index', 'timeout' => 10000, 'enablePushState' => true]); ?>
<?= GridView::widget([...,
[
'label' => 'Status',
'format' => 'raw',
'value' => function ($data) {
if ($data->deactive == 0) {
return Html::a(FA::i('circle'), ['agency/change-status', 'id' => $data->member_id, 'set' => 1], ['onclick' => "return confirm('Deactive this state/site?');", 'class' => 'status-inactive']);
} else {
return Html::a(FA::i('circle'), ['agency/change-status', 'id' => $data->member_id, 'set' => 0], ['onclick' => "return confirm('Active this state/site?');", 'class' => 'status-active']);
}
},
],
]);
<?php Pjax::end(); ?>
actionChangeStatus() is as below:
public function actionChangeStatus($id, $set) {
if (!empty($id) && isset($set)) {
$localGovt = $this->findModel($id);
$localGovt->deactive = $set;
if ($localGovt->save()) {
Yii::$app->getSession()->setFlash('success-status', 'State Status Changed');
} else {
Yii::$app->getSession()->setFlash('error-status', 'There is some error. Please consult with Admin.');
}
$searchModel = new AgencySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
}
}
Note: I need 'enablePushState' => true for other events, so I can't change it to false inside Pjax::begin
I believe it's
'enableReplaceState' => true
Pass this attribute to Pjax:
Pjax::begin(['enablePushState' => false]);
This worked for me.