How to update field in user table yii2 - yii2

I have modified user table to add one column, the column's name is id_periode, I have advanced template, so from backend controler i want update that column value. I create controller like this
public function actionPindahPeriode($id)
{
$model2 = $this->findModel2($id);
if ($model2->load(Yii::$app->request->post()) ) {
$model2->save();
return $this->render('view',
'model2' => $this->findModel2($id),
]);
}
date_default_timezone_set('Asia/Makassar');
$jam_sekarang = date('h:i:s', time());
$tgl_sekarang=date('Y-m-d');
$model_periode = Periode::find()
->andWhere(['>','mulai_daftar_ulang',$tgl_sekarang ])
->asArray()
->all();
return $this->renderAjax('pindah_periode', [
'model_periode' => $model_periode,
'model2' => $this->findModel2($id),
]);
}
The findModel2 function is like this
protected function findModel2($id)
{
if (($model = User::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
I render that model into a form
<?php $form = ActiveForm::begin(); ?>
<?php $listData=ArrayHelper::map($model_periode,'id',function($model_periode){
return $model_periode['nama_periode'].' Tahun '.$model_periode['tahun'];});?>
<?= $form->field($model2, 'id_periode')->dropDownList($listData, ['prompt' => '']) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-danger']) ?>
</div>
<?php ActiveForm::end(); ?>
The form is working but i can not update the value id_periode column in table user. There is not error showing, any suggestion?

Make sure your new attribute id_periode has a rule defined in the public function rules(){} function, this way $model2->load(Yii::$app->request->post()) will assign this value from the data submitted.
$model->save() returns a bool value whether the record was saved or not. You can use this to your advantage and check whether there are any validation errors.ie:
if($model2->save()) {
return $this->render('view',
'model2' => $this->findModel2($id),
]);
} else {
return $this->renderAjax('pindah_periode', [
'model_periode' => $model_periode,
'model2' => $this->findModel2($id),
]);
}

Option 1 : Check your column fields in User model's validation rules. You need to shift unwanted column fields from required attribute to safe attribute.
Option 2 : try $model2->save(false);. false will override your model rules.

Related

Validation error on custom model attributes not displayed in form

I have a model with the following custom attributes topic_names, topic_details (string fields). I have also a model form with the custom attributes and custom rules. When I insert wrong data in the form fields, there is a model error, but it isn't displayed.
Model code:
......
public function rules()
{
return [
...
[['topics_names','topics_details'],'string'],
[['topics_names'],'checkCorrectAndSetTopics'],
];
}
public function checkCorrectAndSetTopics(){
if($this->topics_names AND $this->topics_details){
$topicsNamesArray = explode(',',$this->topics_names);
$topicsDetailsArray = explode(';',$this->topics_details);
if(sizeof($topicsNamesArray) !== sizeof($topicsDetailsArray)){
$this->addError('topics_names', \Yii::t('app', 'The topics names and details sets have different sizes'));
return FALSE;
}
}
return TRUE;
}
The problem is when the second rules is violeted, the form doesn't show any error, but there is. I checked it debugging the code below.
Form code:
..........
<?php
ActiveForm::$autoIdPrefix = createRandomId();//Function which creates a random id
$form = ActiveForm::begin(
['enableAjaxValidation' => true, "options"=> ["class"=>"extra-form"]]);
?>
<?= $form->errorSummary($model); ?>
<?= $form->field($model, 'topics_names')->textInput()
->label(\Yii::t('app', 'Topics Names'))?>
<?= $form->field($model, 'topics_details')->textarea(['rows' => 6])
->label(\Yii::t('app', 'Topics Details'))?>
........
Controller code:
public function actionAddExtraData($id){
if(!Yii::$app->request->isAjax){
throw new ForbiddenHttpException(\Yii::t('app','Cannot access this action directly.'));
}
$event = $this->findModel($id);
$extraData = ExtraData::find()
->andWhere(['event_id'=>$id])
->one();
if(!$extraData){
$extraData = new ExtraData();
$extraData->event_id = $id;
}else{
$extraData->prePerformForm();//Insert data on custom attributes
}
if(Yii::$app->request->isPost AND Yii::$app->request->isAjax AND Yii::$app->request->post("submitting") != TRUE
AND $extraData->load(Yii::$app->request->post())){
Yii::$app->response->format = Response::FORMAT_JSON;
$validation = ActiveForm::validate($extraData);
return $validation;
}
if ($extraData->load(Yii::$app->request->post()) && $extraData->save()) {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ["success" => TRUE];
} else {
return $this->redirect(Yii::$app->request->referrer);
}
}
return $this->renderAjax('_event_extra_form',['model'=>$extraData,'event'=>$event]);
}
First thing, pretty sure you don't need to return true or false, you just need to add error. Second thing, in your example you name the attribute, you can actually get this when defining the function, so your function could look something like this
public function checkCorrectAndSetTopics($attribute, $model){
if($this->topics_names AND $this->topics_details){
$topicsNamesArray = explode(',',$this->topics_names);
$topicsDetailsArray = explode(';',$this->topics_details);
if(sizeof($topicsNamesArray) !== sizeof($topicsDetailsArray)){
$this->addError($attribute, \Yii::t('app', 'The topics names and details sets have different sizes'));
}
}
}

Yii2 Update query in controller not working

I’m trying to update 'page' column but it is not working. I want to update only one column by changing the data from 4 to 5. The data type is an integer.
View
<div class="row">
<div class="col-sm-12 text-center">
<?= Html::a('Add as memoriam', ['update-status', 'id' => $model->ID], [
'class' => 'btn bg-maroon',
'data' => [
'confirm' => 'Are you sure you want to add '.$model->name.' into the dearly departed?',
'method' => 'post',
],
]) ?>
</div>
</div>
Controller
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->save())
$this->redirect(array('view', 'id' => $model->id));
return $this->redirect(['my-obituary']);
}
1. Using save()
This method will call insert() when $isNewRecord is true, or update() when $isNewRecord is false.
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->save(true, ['page'])) {
$this->redirect(array('view', 'id' => $model->id));
}
return $this->redirect(['my-obituary']);
}
2. Using updateAttributes()
This method is a shortcut to update() when data validation is not needed and only a small set attributes need to be updated. You may specify the attributes to be updated as name list or name-value pairs. If the latter, the corresponding attribute values will be modified accordingly. The method will then save the specified attributes into database.
Note that this method will not perform data validation and will not trigger events.
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->updateAttributes(['page' => 5])) {
$this->redirect(array('view', 'id' => $model->id));
}
return $this->redirect(['my-obituary']);
}

Yii2: how to remove required attribute in a view?

I have a text field that was defined as required in its model. But a view needs not be required. I try this way to remove the required attribute but it doesn't work:
<?= $form->field($model, 'city')->textInput(['required' => false]) ?>
I need to change it in a view or in its controller. But not in its model (because others view needs the required attribute.).
I know how to do it using jQuery but I prefer with PHP/Yii2.
Update (requiered by the nice help of #Muhammad Omer Aslam):
My model is called Persons.
My view is called _form.
My controller is called PersonsControllers. It has the update function:
actionUpdate($id):
public function actionUpdate($id)
{
$model = $this->findModel($id); // How to add my new scenario here?
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_person]);
}
return $this->render('update', [
'model' => $model,
]);
}
You can use scenarios to make the field required or not for the specific view. You can assign the active fields that are required for the scenario, and those fields will be the subject to validation.
I assume the model is Profile. In below example firstname, lastname and city is required in the default scenario.
A model may be used in different scenarios, by default the scenario default is used. Let's say in your case we can declare a scenario special that will only require firstname and lastname. In your model, you will declare a constant for the scenario name, and then override the scenarios() method, key=>value pairs with the active field names being passed in form of an array to the value will be assigned.
namespace app\models;
use yii\db\ActiveRecord;
class Profile extends ActiveRecord
{
const SCENARIO_SPECIAL = 'special';
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_SPECIAL] = ['firstname', 'lastname'];
return $scenarios;
}
}
and then inside your controller/action for that view where you do not want the city field to be required, initialize the Profile model object as below
public function actionProfile(){
$model = new \common\models\Profile(['scenario'=> \common\models\Profile::SCENARIO_SPECIAL]);
return $this->render('profile',['model'=>$model]);
}
Now if you submit the form inside this view it will ask only for the firstname and lastname whereas in your previous forms/views if you try to submit the form it will ask you to provide the city when trying to submit, you don't have to change or add anything for the rest of the forms or the rules.
As you are trying to update the record and do not want the city to be required when updating the record, the only difference that could be is to assign the scenario like below as you are not creating a new object for the model.
$model->scenario=\common\models\Profile::SCENARIO_SPECIAL;
In the model:
const SCENARIO_MYSPECIAL = 'myspecial';
public function rules()
{
return [
[['id_person', 'city'], 'required', 'on' => self::SCENARIO_DEFAULT],
[['id_person'], 'required', 'on' => self::SCENARIO_MYSPECIAL],
];
}
In the controller:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'myspecial';
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_person]);
}
return $this->render('update', [
'model' => $model,
]);
}
go to the model and remove the attribute
public function rules()
{
return [
[['id_person', 'city'], 'required'],
[['id_person'], 'required'],
];
}
EX:
public function rules()
{
return [
[['id_person'], 'required'],
[['id_person'], 'required'],
];
}

How to create a new input field which would offer values stored in different database table? Yii2

It's pretty hard to formulate the question correctly, but I'll try to explain it more here. I have an Item, Category and Sale models. In category and Item models I manually stored data. Now I've created a form, which has some input fields and dependent drop-down, which is:
According to the selected category, items are loaded.
Now I need to create a new input field, which would be price and it has to be taken from the database as a offer (f.e if the user selects Item1 -> Item1 price has to be loaded up as a offer in the input field, which I could edit it and store in different database table.
How should I do that?
Here is my SaleController action:
/**
* Creates a new sale
*
* #return string
*/
public function actionCreate()
{
$model = new Sale();
$model->scenario = Sale::SCENARIO_CREATE;
$category = new Category();
$category->scenario = Category::SCENARIO_CREATE;
$categoryList = ArrayHelper::map(Category::find()->all(), 'id', 'name');
if ($model->load(Yii::$app->request->post())) {
if ($model->save()) {
return $this->redirect(['index']);
}
}
return $this->render('create', [
'model' => $model,
'category' => $category,
'categoryList' => $categoryList,
]);
}
And here is my view:
<?= $form->field($category, 'id')->dropDownList($categoryList, [
'id' => 'category-id',
'prompt' => 'Choose a category',
]); ?>
<?= $form->field($model, 'item_id')->widget(DepDrop::classname(), [
'options'=>['id'=>'item-id'],
'pluginOptions'=>[
'depends'=>['category-id'],
'placeholder'=> 'Choose an item',
'url'=>Url::to(['/sale/subcat'])
]
]); ?>
<?= $form->field($model, 'price') ?>
Thank you for any help. I hope you understand the question
First you must add an input field in your view from model:
<?= $form->field($model, 'item_price')->textInput([
'maxlength' => true,
'id' => 'input-price-id'
]) ?>
Then you need to add some javascript:
<?php
$item_price=<<<JS
$('#item-id').on('change', function(event) {
var id = $(this).attr('id');
var val = $(this).val();
.get(
// you must code function actionRefreshPrice wtih parameter named item_id in
// your controller with fetch from any table you want
'refresh-price',
{
item_id: val // this is id from your item
},
function (data) {
// here you set a value returned from ajax call
// you must have an input element with id input-price-is (change as you like)
$('#input-price-id').val(data);
}
);
});
JS;
$this->registerJs($item_price);
?>
Then you must add a controller action something like this:
public function actionRefreshPrice($item_id) {
// I asume you have table with Price for items prices
$price = Price::findOne(['item_id'=>$item_id]);
return ($price?0:$price->price_field);
}
I hope I have given you enough guidelines. And a comment learn more about models and relations. I think you overthought problem a little bit. Happy learning and coding.

Initial Values for an array-type attribute in Yii2 Model

If an attribute in a Model holds array data, say Dates, that are populated in a form with multiple rows for this attribute, how may I assign initial values to the array elements so that they display initially in the form when it appears.
In my example, my array-type attribute holds dates and I want each new date row in the form to have different values when the form loads.
<?= $form->field($model, 'datesToPay[]') ?>
I tried to use the DefaultValueValidator filter of Yii2 to assign initial value to the datesToPay array elements but it does not show the value when the form loads.
['datesToPay', 'each', 'rule' => ['default', 'value' => date('Y-m-d')]]
You can do in the controllerAction before render
public function actionCreate()
{
$model = new MyModel();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
$model->datesToPay[0] = 'YourValue';
return $this->render('create', [
'model' => $model,
]);
}
}