I have a form, when clicking on the icon the class should switch to enabled/disabled
$options = [
'enablePushState' => false,
'timeout' => 5000,
'options' => ['tag'=>'span', 'class'=>'access']
];
$id = \Yii::$app->request->get('_pjax');
if($id){$options['id'] = str_replace('#', '', $id);}
?>
<?php Pjax::begin($options); ?>
<?= Html::a('<i class="fa fa-users"></i>', ['/request/'.$id.'/access'], [
'class' => ($access['provider'] ?? null) ? 'enabled' : 'disabled'
]) ?>
<?php Pjax::end(); ?>
public function actionAccess($id){
$requestModel = $this->model->getRequestModel($id);
$this->model->requestToggleAccess($requestModel);
$access = $requestModel->checkAccess();
return $this->renderPartial('access.php', [
'id' => $id,
'access' => $access
]);
}
public function getRequestModel($id)
{
$requestModel = RequestModel::findOne($id);
return $requestModel;
}
public function requestToggleAccess($requestModel)
{
if (Yii::$app->request->isPjax) {
$access = $requestModel->checkAccess();
if( $access['provider'] ){
$request->accessRoleIds = null;
}else{
$request->accessRoleIds = [ROLE_PROVIDER, ROLE_PROVIDER_WORKER];
}
$request->saveAccess();
}
}
public function checkAccess()
{
return self::checkAccessBy($this->access);
}
public static function checkAccessBy($arr)
{
$access = [];
if(empty($arr)){return $access;}
foreach ($arr as $acc){
if(in_array($acc->role_id, [ROLE_PROVIDER, ROLE_PROVIDER_WORKER])){
$access['provider'] = true;
}
}
return $access;
}
The thing is that when initially the class is enabled and I switch to disabled, then everything works well, but when I switch in the reverse order from disabled to enabled, then I just go to this link '/request /'.$id.'/access' and returns an empty page, it gives an error 500 without any details.
I'm trying to dump to find the problem
In the actionAccess function after calling the function checkAccess(), I added
var_dump($access['provider']);
exit();
And got an error
Undefined array key "provider"
Although in the neighboring function requestToggleAccess there is the same checkAccess() call, after which I added the same dump, and instead of an error I get boolean(true), which is what it should be
What could be the problem?
Look into
requestToggleAccess. The problem is that you assume$access['provider']to exist. But insidecheckAccessBy(which is called bycheckAccessand whose return value will be assigned to$access) you will see that$access['provider']is not necessarily defined. We will return to this problem at the end of this answer, but first, let's makerequestToggleAccessless error-prone:I have merely added a
?? falseto yourifcondition, that is, we know that$accessis defined at this point, but we avoid assuming that it has a value. Instead, we evaluate it and gather its value if it exists, defaulting tofalseif it did not exist.Now, let's see why
checkAccessBydid not specify$access['provider']. There you receive an array (afterself::checkAccessBy($this->access)is called) and you loop that array. For each item in that array, you check whetherin_array($acc->role_id, [ROLE_PROVIDER, ROLE_PROVIDER_WORKER])and if so, then you set$access['provider']totrue. But you never ever set it tofalse. This is an improved version of the same method:I have changed the initialization of
$accessso it will have a provider element, which is initialized withtrueand overriden later if needed.Another change you might want to make is to return
$accessinside the loop if its provider is to be set tofalse, but I did not do that, because you might prefer to return it at the end of the method for styling or other purposes.