Yii2 - Update database field when switchinput widget is clicked - yii2

I am using the switchinput Kartik widget which I have related to a database true/false field (field1). What I want to do is to be able to update this database field value when I change the switch.
Here is the view code:
<?php
echo $form->field($model, 'field1')->widget(SwitchInput::classname(), [
'type' => SwitchInput::CHECKBOX,
'name' => 'status_11',
'pluginOptions' => [
'size' => 'medium',
'onColor' => 'success',
'offColor' => 'danger',
'handleWidth'=>80,
'onText'=>'ACTIVE',
'offText'=>'INACTIVE'
]
]);
?>
and here is the controller code that tries to update the database:
.................
if (isset($_POST['status_11']))
{
if ($model->field1 == False)
{
$model->field1 = True;
}
else
{
$model->field1 = False;
}
}
if(!$model->save())
{
throw new Exception('Could not save to database. Trnasaction aborted.');
}
..................
The switch can read from the database the value of field1 and show on or off respectively. But the change (onclick) action does not update the database...
Should I try using PHP or should I implement it with js ('pluginEvents' widget option) and how?
Any suggestions would be highly appreciated. Thank you in advance.

You should use the pluginEvents array with the switchChange event, to trigger an ajax call to your php script, which updates the database:
pluginEvents = [
"switchChange.bootstrapSwitch" => 'function() {
$.ajax({
method: "POST",
url: "'.Url::to(['/controller/action']).'",
data: { status_11: state}
})
}',
];

Related

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

How to force data update on laravel validation custom unique

I'm new in laravel. I have a table with menu_id and title I tried to make this title field unique when have the same menu_id. I found the solution here
But I got problem when update it. Can anyone help please?
My code
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// Check the table and return true only if there are no entries matching
// both the first field name and the user input value as well as
// the second field name and the second field value
return \DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});
public function updateSubmenu( Request $request) {
$this->validate( $request, [
'menu_id' => 'required',
'title' => 'required|unique_custom:posts,title,menu_id,'.$request->menu_id,
'order_by' => 'required|integer',
'description' => 'required'
],
[
'title.unique_custom' => 'This title already token'
]
);
}
Can you explain what problem have you got on update? Some exception?
Edit:
If you couldn't update record if title not changes, you need to add one condition to Validator:
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// If old value not changed, don't check its unique.
$current = \DB::table($table)->where('title')->first();
if( $current->{$field} == $value) {
return true;
}
return \DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});

Yii2: Validate content of a file before submitting

In my form I have a field for the user to upload an XML file. But before submitting the XML, I have to validate it. How can I create a validation function for this?
My view:
...
<?= $form->field($model, 'upload_file')->fileInput(['accept' => 'text/xml']) ?>
...
My Model:
...
['upload_file', 'validateFile'],
...
public function validateFile($attribute, $params)
{
// TODO
}
...
I can access and validate the contents of the XML file in the controller, but this validation is already after the file is submitted ... I wanted before submitting!
Exemple in controller:
if ($model->load(Yii::$app->request->post()) {
$file = UploadedFile::getInstance($model, 'upload_file');
$file = file_get_contents($file->tempName);
// xml of the upload_file
$xml = simplexml_load_string($file);
I want to pass this code that is on top, to the validation function.
Add this to your model rules:
public function rules()
{
return [
[['uploaded_file'], 'file', 'skipOnEmpty' => false, 'extensions' => 'xml', 'mimeTypes' => 'text/xml, application/xml'],
];
}

How to update customer in braintree payment method

I have integrated braintree method in yii2 rest api Using this reference.. I want to update the customer but I am getting following error:
Missing argument 2 for Braintree\Customer::update()
Below is my code :
$braintree = Yii::$app->braintree;
$response = $braintree->call('Customer', 'update','15552090',[
'firstName' => 'test-1545',
'lastName' => 'asdf',
'company' => 'New Company',
'email' => 'new.email#example.com',
'phone' => 'new phone',
'fax' => 'new fax',
'website' => 'http://new.example.com'
]);
print_r($response); die;
I am stack here how to pass the arguments?
It's a problem of this particular extension. See this issue on Github.
Issue OP recommends this fix:
public function call($command, $method, $values, $values2 = null)
{
$class = strtr("{class}_{command}", [
'{class}' => $this->_prefix,
'{command}' => $command,
));
if ($values2) {
return call_user_func(array($class, $method), $values, $values2);
else {
return call_user_func(array($class, $method), $values);
}
}
while extension author recommends this:
if (is_array($values)) {
call_user_func_array(...);
} else {
call_user_func(...);
}
Either way you need to override this component with your own and apply a patch.
Note that the amount of code in application is small (64 lines in one file) so you can create your own wrapper or find better one because this issue is still not fixed.
And maybe is better to directly use braintree_php methods which will be more clear than magical call.
Update: To override component, create own class extending from bryglen's, place it for example in common/components folder in case of using advanced app.
namespace common\components;
class Braintree extends \bryglen\braintree\Braintree
{
public function call($command, $method, $values)
{
// Override logic here
}
}
Then replace extension class name with your custom one in config:
'components' => [
'braintree' => [
'class' => 'common\components\Braintree',
'environment' => 'sandbox',
'merchantId' => 'your_merchant_id',
'publicKey' => 'your_public_key',
'privateKey' => 'your_private_key',
],
],

yii2 How to transfer post data from one view to two?

I am trying to create make a two-step form in yii2.
This is my SiteController.php
public function actionCreateCharacter()
{
$model = new Character();
var_dump(Yii::$app->request->post('Character'));
if ($model->load(Yii::$app->request->post())) {
$attributes=['imie','nazwisko','plec','wyznanie_id'];
if ($step1 = $model->validate($attributes)) {
//var_dump($step1);
// form inputs are valid, do something here
//var_dump(Yii::$app->request->post('Character');
return $this->render('createCharacterStep2', [
'model' => $model,
]);;
}
else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
}
}
return $this->render('createCharacter', [
'model' => $model,
]);
}
public function actionCreateCharacterStep2()
{
$model2 = new Character();
var_dump($model);
if ($model2->load(Yii::$app->request->post())) {
var_dump(Yii::$app->request->post('Character'));
if ($model2->validate()) {
// form inputs are valid, do something here
return;
}
}
/*return $this->render('createCharacter2', [
'model' => $model,
]);*/
}
... and this is my Character.php (model + attributeLabels and tableName)
public function rules()
{
return [
[['user_id', 'imie', 'nazwisko', 'plec', 'wyznanie_id', 'avatar_src', 'avatar_svg'], 'required'],
[['user_id', 'wyznanie_id'], 'integer'],
[['avatar_svg'], 'string'],
[['imie'], 'string', 'max' => 15],
[['nazwisko'], 'string', 'max' => 20],
[['plec'], 'string', 'max' => 1],
[['avatar_src'], 'string', 'max' => 30]
];
}
I have access to $_POST by Yii::$app->request->post() in createCharacter - I get imie, nazwisko, plec and wyznanie_id.
But when I send the form in step 2 I have only post data from step 2.
How can I set the post data from step1+step2?
Sorry for my english and thanks in advance.
While rendering step2 from step1 action, you can always pass additional data to controller's action. So I added "STEPONEPOSTS" post variable which contains all posts of step 1. Check below.
public function actionCreateCharacter()
{
$model = new Character();
var_dump(Yii::$app->request->post('Character'));
if ($model->load(Yii::$app->request->post())) {
$attributes=['imie','nazwisko','plec','wyznanie_id'];
if ($step1 = $model->validate($attributes)) {
//var_dump($step1);
// form inputs are valid, do something here
//var_dump(Yii::$app->request->post('Character');
return $this->render('createCharacterStep2', [
'model' => $model,
'STEPONEPOSTS' => Yii::$app->request->post(),
]);;
}
else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
}
}
return $this->render('createCharacter', [
'model' => $model,
]);
}
And now in step 2 view, you can get step 1 posts variable as
$STEPONEPOSTS
There is another way , if you have to table for step 1 and step 2. then save the data of step 1 first then step2 data. if you are not using two tables then you can create two form each form for each step and also create scenarios for each step according to the fields.I think this may help . You can use session also as per discussion in comments or you can use the extension array wizard but array wizard extension is not well documented , so i suggest you try my way i will help you.