the below coding might have logic error which I cannot identify since I'm not so good in logic.
public function actionSave()
{
//initiate connection
$request = Yii::$app->request;
if (Yii::$app->request->post())
{
//receive from POST, insert into $student
$student=Yii::$app->request->post('sudent');
//receive from POST, insert into $selection
$selection=Yii::$app->request->post('selection');
//looping foreach and set $student as $key
foreach ($student as $key => $value)
{
if($key==0 )
{
$check=$selection[$key];
}
elseif($key)
{
$check=empty($selection[$key])?'':$selection[$key];
}
else{
//don't know what to do here
}
$model=new Attendance();
if($check || $check==0)
{
$model->student_id=$value;
$model->attendance_check=1;
$model->attendance_date=time();
// $model->attendance_reason=$value;
$model->save();
}
else
{
$model->student_id=$value;
$model->attendance_check=0;
$model->attendance_date=time();
// $model->attendance_reason=$value;
$model->save();
}
}
}
else
{
//don't know what to do here
}
}
the flow is, when this controller receive from POST (checked box and some texfields) it will go to foreach and check if the checkbox==1 (means it is ticked) it wil insert to databse. if not, still insert into database but with value 0.
one from 7 checkbox i did not tick. so, in database 6 attendance_check will hold value 1 and 1 attendance_check hold value 0.
what i get? all hold value 1.
what are the error?
Thanks.
--update 22/3/2016--
the form view (named index.php)
<?php
use yii\grid\GridView;
use yii\data\ActiveDataProvide;
use yii\grid\CheckboxColumn;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\Url;
//active form start
$form = ActiveForm::begin([
//send to 'key-in-attendance/save'
'action' => Url::to(['key-in-attendance/save']),
]) ?>
<?php
//keluarkan grifview
echo GridView::widget([
'dataProvider' =>$dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'student_name',
'class_id',
//checkbox untuk kehadiran
['class' => 'yii\grid\CheckboxColumn',
'checkboxOptions'=>['style'=>'display: block;margin-right: auto;margin-left: auto;'],
'header' => Html::checkBox('selection_all', false, [
'class' => 'select-on-check-all pull-right',
'label' => '<span class="pull-left">Check Attend Only</span>',//pull left the label
]),
'checkboxOptions' => function ($data, $key, $index, $column)
{
return ['value' => $index];
}
],
//text box utk masukkan sebab tak hadir
[
'class' => 'yii\grid\DataColumn',
'label'=> 'Reason not attend',
'value' => function ($data)
{
return Html::textarea("reason".$data->id);
},
'format'=>'raw'
],
[
'class' => 'yii\grid\DataColumn',
'value' => function ($data)
{
return Html::hiddeninput("sudent[]",$data->id);
},
'format'=>'raw'
],
],
]);
?>
<!-- butang submit dan tutup active form -->
<div class="form-group">
<div class="col-lg-offset-1 col-lg-11">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
--update 23/3/2016--
selection that I made
in the database
Select is already going to be indexed by the ID of your data provider, so the sudent array is unnecessary.
The following should work.
public function actionSave()
{
//initiate connection
$request = Yii::$app->request;
if (Yii::$app->request->post())
{
//receive from POST, insert into $selection
$selection=Yii::$app->request->post('selection');
//looping foreach and set $student as key
foreach ($selection as $value => $check)
{
$model=new Attendance();
$model->student_id=$value;
$model->attendance_check=$check ? 1 : 0;
$model->attendance_date=time();
// $model->attendance_reason=$value;
$model->save();
}
}
else
{
//don't know what to do here
}
}
One more thing to consider is that you are creating new Attendance records but responses might already have been recorded, you want to load first.
$model = Attendance::findOne(['student_id'=>$value]);
if(!$model) $model = new Attendance();
Related
I am working on yii2. I have a form in which there are 3 dropdowns.
use kartik\select2\Select2;
<div class="allow-area-form">
<?php $form = ActiveForm::begin(); ?>
<?=
$form->field($model, 'city_name')
->widget(Select2::className(),[
'data' => \common\models\AllowArea::toCityArrayList(),
'options' => ['placeholder'=>'Select Area'],
'pluginOptions' => [
'allowClear' => true,
'multiple' => true
],
]);
?>
<?=
$form->field($model, 'user_id')
->widget(Select2::className(),[
'data' => \app\models\User::toArrayList(),
'options' => ['placeholder'=>'Select a User'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<?=
$form->field($model, 'salesman_code')
->widget(Select2::className(),[
'data' => \common\models\AllowArea::toArrayList(),
'options' => ['placeholder'=>'Select A Booker'],
'pluginOptions' => [
'allowClear' => true,
],
]);
?>
<div class="form-group">
<?= Html::submitButton(Yii::t('app', 'Save'), ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
Interface
In, the above the areas can be selected multiple. Users can only be one and a booker is also one. A single area have multiple sub-areas. So when the main area is selected all of its sub-areas are allotted to a user. So for example, if I select 3 Main-Areas and each of them has 10 sub-areas, a single user is allowed 30 sub-areas. For this purpose, I have implemented the following in my controller
public function actionCreate()
{
$model = new AllowArea();
if (isset($_REQUEST['AllowArea'])) {
try {
$m = new AllowArea();
foreach ($_REQUEST['AllowArea']['city_name'] as $a=>$b)
{
$sql = "select AreaCode from area where CityNameFull = '$b'";
$res = Yii::$app->sds->createCommand($sql)->queryAll();
foreach ($res as $r)
{
$m->load(Yii::$app->request->post());
$areacode = $r['AreaCode'];
$query = "select AreaNameFull from area where AreaCode = '$areacode'";
$rst = Yii::$app->sds->createCommand($query)->queryOne();
$areaname = $rst['AreaNameFull'];
$m->area_code = $areacode;
$m->area_name = $areaname;
$m->user_id = $m['user_id'];
$m->user_name = AllowArea::idTouser($m['user_id']);
$m->salesman_code = $m['salesman_code'];
$m->salesman_name = AllowArea::idTousersalesman($m['salesman_code']);
$m->city_name =$b;
$m->created_by = Yii::$app->user->id;
$m->created_at = date('Y-m-d H:i:s');
$m->save();
}
}
}catch (Exception $e) {
return $this->redirect(['index']);
}
return $this->redirect(['index']);
}
return $this->render('create', [
'model' => $model
]);
}
Data
Below is the database table result of a single selected main area.
So if I select ALLAMA IQBAL TOWN-01(ALL-BLOCK) in the main area, all of the 20 sub-areas should be saved. But my controller only saves the last ZEENAT BLOCK AIT sub-area and leaves the rest of the remaining.
I have also checked the data inside the 3rd foreach loop, it does get the first item but saves the last one so it means that all of the 20 sub-areas are inside the loop.
There must be some mistake that my code is not saving the data and I am stuck in it.
How to save all the data?
Any help would be highly appreciated.
You are reusing the same AllowArea model $m so it is adding a single entry to your table and updating it 19 times. Move the $m = new AllowArea() into the loop:
try {
foreach ($_REQUEST['AllowArea']['city_name'] as $a=>$b)
{
$sql = "select AreaCode from area where CityNameFull = ':cityName'";
$res = Yii::$app->sds->createCommand($sql, [':cityName' => $b])->queryAll();
foreach ($res as $r)
{
$m = new AllowArea();
...
As an aside, your code is vulnerable to SQL injection since you aren't validating the value of $b so you should use a prepared statement instead as in the code above or consider using the ActiveRecord functions to fetch the AreaCodes.
I have a model with a custom validation method. For testing it always returns an error message.
public function rules()
{
return [
...
['staff_ids', 'each', 'rule' => ['string']],
[['staff_ids'], 'validateStaffIds'],
...
];
}
public function validateStaffIds($attribute, $params, $validator) {
$this->addError($attribute, 'There is an error in the staff ids');
}
In the view.php is the modal element
<p>
<?= Html::button('Add Ensemble Staff',
['value' => Url::to(['ensemble/add', 'id' => $model->id]),
'title' => 'Adding New Ensemble Staff',
'class' => 'showModalButton btn btn-primary']);
?>
</p>
<?php
Modal::begin([
'closeButton' => [
'label' => 'x',
],
'headerOptions' => ['id' => 'modalHeader'],
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
The js code which fires everything up...
$(function(){
$(document).on('click', '.showModalButton', function(){
if ($('#modal').data('bs.modal').isShown) {
$('#modal').find('#modalContent')
.load($(this).attr('value'));
} else {
//if modal isn't open; open it and load content
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
}
//dynamiclly set the header for the modal
...
});
});
And the ensemble controller which handles the add action
public function actionAdd($id)
{
$model = $this->findModel($id);
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
And the form which is injected by the js into the model (Url::to(['ensemble/add', 'id' => $model->id]), )
<?php $form = ActiveForm::begin(['id' => 'add-theater-stuff-form']); ?>
<?= $form->field($model, 'staff_ids')->widget(Select2::className(), [
'model' => $model,
'data' => ArrayHelper::map(app\models\TheaterStaff::find()->where(['theater_id' => $model->theater_id])->all(), 'staff_id', 'staff.fullname'),
'options' => [
'multiple' => true,
'prompt' => 'Ensemble Staff',
],
'pluginOptions' => [
'tags' => true
]
]); ?>
<div class="form-group">
<?= Html::submitButton('Add', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Clicking on the Add Ensemble Staff Button works fine and brings up the modal window. The form itself works fine so far; also the default validation works. Even the custom validation is called, but return $this->renderAjax(...) isn't load in the modal window anymore; it is separately.
A picture showing the modal loaded, the result after submit and a modal with default validation.
I found a similar problem here. But adding an id to the form, doesn't solve the problem. So how to get the default validation showing up properly in the modal window? Does anyone have a clue?
Solution
Thanks for the response. For me the solution was:
Enable ajax in the form
<?php $form = ActiveForm::begin(['id' => 'add-ensemble-stuff-form', 'enableAjaxValidation' => true]); ?>
And to add the following logic in the controller
public function actionAdd($id)
{
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
} else {
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
}
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}else{/* your code */}
add this in controller use yii\web\Response
I have two models in a form.
One model is a master, and one model is representated as junction table (model).
Desc :
request_table : $model,
link_req_tipe : $modelLinkReqTipe;
My goal is,
I save the $model, then I get the $model->id
I batch insert to link_req_item
id_request = $model->id and id_tipe = modelLinkReqTipe->id_tipe
Here it is the php :
_form.php (just example, because a lot of many input form)
<?= $form->field($model, 'karyawan_id')->dropDownList(
ArrayHelper::map(Karyawan::find()->all(), 'id', 'first_name'), ['prompt' => 'Select Karyawan'])
?>
<?= $form->field($modelLinkReqTipe, 'id_tipe')->checkBoxList(ArrayHelper::map(TipeRequest::find()->all(), 'id', 'nama_tipe'));
?>
RequestController
if ($model->load($request->post()) && $modelLinkReqTipe->load(Yii::$app->request->post())) {
$valid = $model->validate();
$valid = $modelLinkReqTipe->validate() && $valid;
if ($valid) { ## Check validate : true
$transaction = Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelLinkReqTipe as $index => $modelLinkReqTipe ) {
if ($flag === false) {
break;
}
$modelLinkReqTipe->id_request = $model->id;
if (!($flag = $modelLinkReqTipe->save(false))) {
break;
}
}
}
if ($flag) {
$transaction->commit();
} else {
$transaction->rollBack()
}
}
catch (\Exception $e) {
$transaction->rollBack();
}
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new Request",
'content' => '<h1 class="text-success">Success</h1>,
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
}else{ ## Check validate : false
return [
'title' => "Create New Request",
'content' => $this->renderAjax('create', [
'model' => $model,
'modelLinkReqTipe' => (empty($modelLinkReqTipe)) ? new LinkReqTipe() : $modelLinkReqTipe,
'modelLinkReqItem' => (empty($modelLinkReqItem)) ? [new LinkReqItem] : $modelLinkReqItem,
]),
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::button('Save', ['class' => 'btn btn-primary', 'type' => "submit"])
];
}
Now, validation is in trouble,
it always return false in submit.
Please Advise.
There are many ways to resolve this issue. I think the best way to make sure that $modelLinkReqTipe's attribute id_request is not taken into account upon validation is to provide validate() function with array of attributes you want to validate: validate(['id_tipe'])
I got two related tables(models) [Sub with primary key id] and [Case with foreign key sub_id]. I created Sub with id=4. I want to create data of Case model in view.php(form) of Sub model. I did a "Create Case" Button which refer to the actionCreate of Case model.
This is my "Create Case" button in sub/view.php:
<?= Html::a(Yii::t('app','Create Case'), ['/case/create', 'sub_id' => $model->id], ['class' => 'btn btn-primary']) ?>
It looks like in the
picture
This button referred me to the create form of Case model, where i should get the field sub_id = 4. Now my _form.php has
<?= $form->field($model, 'sub_id')->textInput() ?>
What should i change to get the automatically filled field sub_id with id of parent model?
UPDATE: I added relevant code from the appropriate view, controller files.
I didn't changed model files.
CaseController.php file looks like shown below
class CaseController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
public function actionIndex()
{
$searchModel = new CaseSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
public function actionCreate($sub_id)
{
$model = new Case();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'parent' => $sub_id
]);
}
}
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,
]);
}
}
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
protected function findModel($id)
{
if (($model = Case::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
sub/view.php file:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
$this->title = $model->id . ": " . $model->fullname;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Subs'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="sub-view">
<h3><?= Html::encode($this->title) ?></h3>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'address_id',
'address.region.name',
[
'label' => 'address',
'value' => 'Street: ' . $model->address->street . ' House ' . $model->address->house . ' Flat ' . $model->address->flat
],
],
]) ?>
<p>
<?= Html::a(Yii::t('app', 'Create Case'), ['/case/create', 'sub_id'=>$model->id], ['class' => 'btn btn-success']) ?>
</p>
</div>
case/_form.php file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
<div class="case-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'id')->textInput() ?>
<?php if($model->isNewRecord && isset($parent_id)) {
$model->sub_id = $parent_id;
} ?>
<?= $form->field($model, 'sub_id')->textInput(['readonly' => true, 'value' => $model->sub_id]) ?>
<?= $form->field($model, 'case_date')->textInput() ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
With lack of any further information, to the best of my understanding this is what you are asking -
Taking the example in your picture, if user clicks on Create Case button, then a new form (Create Case) will open. In that Create Case form, among other input fields, there is a field for sub_id and it should be populated by default with the value 4 (since in the picture the ID of the User Harry Potter is 4).
Based on the above you simply need to do the following -
In your action (within the CaseController) for create case, you pass the sub_id like below -
/* ** CaseController ** */
public function actionCreate($sub_id)
{
//....other code
return $this->render('create', ['model' => $model,'parent_id' => $sub_id]);
}
And then inside the _form.php where you are showing the Create Case form you simply do like this -
/* ** _form.php ** */
//... other code
//if you are using _form.php for Edit Form as well,
//this prevents the value from the DB being over-written
if($model->isNewRecord && isset($parent_id)) {
$model->sub_id = $parent_id;
}
<?= $form->field($model, 'sub_id')->textInput() ?>
//... other code
This should be enough to display the value passed from the parent form.
Hi I have 2 tables and models for them. First of them is
User
and second
News
I want to take user id from table News and draw her name and surname. There is printscreen of table News:
I am trying to use the function:
public function getUrUser()
{
$q= News::find()->where(['urUser_Id' =>'Id'])->one();
$RoyalUserData=User::findOne($q);
//$RoyalUserData= User::find()->where(['Id' => $q])->one();
return $RoyalUserData->Name;
}
But this doesnt work. Only when I prescribe to q value 3 for egzample then it work. I know that is the wrong code in my first line of my function probably. I know that is easy but I am a beginner and I've fought with the code for about 1 hour. Can anyone help me?
In my view I use this:
<?=$model->getUrUser();?>
And I use this in ListView.
My controller:
public function actionIndex()
{
$model = new NewsForm();
$searchModel = new NewsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$dataProvider->setSort(['defaultOrder' => ['Id'=>SORT_DESC]]);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->saveNews();
return $this->redirect(['/content/news']);
} else {
return $this->render('index', [
'model' => $model,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
}
My index where i use _item:
echo ListView::widget( [
'dataProvider' => $dataProvider,
'itemView' => '_item',
], $options = ['class' => 'sorter'] ); ?>
And content of _item
<?php
use yii\helpers\Html;
?>
Treść Newsa:
<?=$model->Text;?> <br>
Autor:
<?=Yii::$app->user->identity->Name?>
<?=Yii::$app->user->identity->Surname?> <br>
Status Newsa:
<?=$model->cnNewsContentType_Id;?> <br>
<?= Html::a('Update', ['update', 'id' => $model->Id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Delete', ['delete', 'id' => $model->Id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?><br><br><br>
The News::find()->where(['urUser_Id' =>'Id'])->one() return a model not a field
then you must get the id field by the model this way
public function getUrUser($id)
{
// you already have the news model so don't need retrieve it
// it's enough pass the urUser_Id by $id
$RoyalUserData=User::findOne($id);
return $RoyalUserData->Name;
}
Then if you want show the ($RoyalUserData) Name in _item
<?=$model->getUrUser($model->urUser_Id);?>
public function getUrUser()
{
$q = News::find()->where(['urUser_Id' =>'Id'])->one();
return $q->user->name;
}
In user model you should create relation:
class News extends ActiveRecord
{
// ...
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
}