How to make validations from a query to a table? yii2 - yii2

my problem is: I have a form where i have select2 and the user can select from a dropdown list which is populated from a table, so, basically what i want to happen is that when the user tries to select a driver a validation rule will take place which will check if the driver was already registered through the system that day.
I have one idea of how to do it, i have my archive form which registers people that enter in the archive table, it checks wether it exists or not in the drivers table and if not you have to register them, if they exists you proceed to fill out the form, each field in the this archive table has a datecreated column which is the date the field was entered, so basically the last time he came in.
How can i make a rule which calls for this column compares to current day and gives an error if he had already entered that day? The rule should be in drivers model.(My code is confusing that is why i'm clarifying, i'm new to Yii2)
My view (archive form):
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use wbraganca\dynamicform\DynamicFormWidget;
use app\models\Drivers;
use app\models\Vehicles;
use app\models\Invoices;
use dosamigos\datepicker\DatePicker;
use kartik\select2\Select2;
use yii\bootstrap\Modal;
use yii\helpers\Url;
/* #var $this yii\web\View */
/* #var $model app\models\Archive */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="archive-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']); ?>
<?= $form->field($model, 'driver_identitynum')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Drivers::find()->all(),'driver_identitynum', 'fullname'),
'language' => 'en',
'options' => ['placeholder' => 'Ingrese el numero de cedula...'],
'pluginOptions' => [
'allowClear' => true],
]); ?>
<div align="right"><?= Html::a('Add driver', ['/drivers/create'],
['target'=>'_blank']); ?>
</div>
<?= $form->field($model, 'vehicle_lp')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Vehicles::find()->all(),'vehicle_lp', 'fulltruck'),
'language' => 'en',
'options' => ['placeholder' => 'Ingrese la placa del vehiculo...'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
<div align="right"><?= Html::a('Add vehicle', ['/vehicles/create'],
['target'=>'_blank']); ?>
</div>
<div class="row"> <div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i>Facturas</h4></div>
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 4, // the maximum times, an element can be cloned (default 999)
'min' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsInvoices[0],
'formId' => 'dynamic-form',
'formFields' => [
'invoice_number',
'invoice_loadamount',
'invoice_date',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsInvoices as $i => $modelInvoices): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">Facturas</h3>
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<?php
// necessary for update action.
if (! $modelInvoices->isNewRecord) {
echo Html::activeHiddenInput($modelInvoices, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_number")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_loadamount")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_date", ['enableAjaxValidation' => true])->widget(DatePicker::className(), [
// inline too, not bad
'inline' => false,
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'options' => ['class' => 'form-control picker'],
'clientOptions' => [
'autoclose' => true,
'format' => 'dd-mm-yyyy'
]
]);?>
</div>
</div><!-- .row -->
<div class="row">
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
My drivers model:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "drivers".
*
* #property integer $driver_id
* #property string $driver_name
* #property string $driver_lastname
* #property string $driver_identitynum
*/
class Drivers extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'drivers';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['driver_name', 'driver_lastname', 'driver_identitynum'], 'required'],
[['driver_name', 'driver_lastname', 'driver_identitynum'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'driver_id' => 'Driver ID',
'driver_name' => 'Driver Name',
'driver_lastname' => 'Driver Lastname',
'driver_identitynum' => 'Driver Identitynum',
];
}
public function getfullName()
{
return $this->driver_identitynum.' - '.$this->driver_name.' '.$this->driver_lastname.' ';
}
/**
* #return \yii\db\ActiveQuery
*/
public function getArchives()
{
return $this->hasMany(Archive::className(), ['driver_identitynum' => 'driver_identitynum']);
}
}
My archive model:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "archive".
*
* #property integer $id
* #property string $driver_identitynum
* #property string $vehicle_lp
* #property string $DateCreated
*
* #property Invoices[] $invoices
*/
class Archive extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'archive';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['driver_identitynum', 'vehicle_lp'], 'required'],
[['DateCreated'], 'safe'],
[['driver_identitynum', 'vehicle_lp'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'driver_identitynum' => 'Cedula del conductor:',
'vehicle_lp' => 'Placa del vehiculo:',
'DateCreated' => 'Date Created',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getInvoices()
{
return $this->hasMany(Invoices::className(), ['archive_id' => 'id']);
}
public function __toString()
{
return 'CI:'.$this->driver_identitynum.' Placa: '.$this->vehicle_lp;
}
public function didheloadtoday($attribute,$params)
{
$inputlp=($this->invoice_loadamount);
$row = (new \yii\db\Query())
->select('vehicle_lp')
->from('vehicles')
->where("vehicle_lp=$vehiclelp")
->all();
}
}

So, the rule is that only one driver_identitynum and DateCreated combination can exist in the archive table.
To validate the driver_identity field for this you can use the native unique validator and specify the attributes that need to be unique together.
The corresponding rule would be:
[['driver_identitynum'], 'unique',
'targetAttribute' => ['driver_identitynum', 'DateCreated'],
],
If this validation is called from another model, then it complicates matters a bit. In addition to the above:
specify the target class
declare a public date variable in the other model
store current date in this field
indicate the this date property should be used as value to check uniqueness of DateCreated
The adjusted rule would be:
[['driver_identitynum'], 'unique',
'targetAttribute' => ['driver_identitynum', 'date' => 'DateCreated'],
'targetClass' => '\app\models\Archive'
],

Related

Yii2 - Two models in one form - Values are not saved in the second model

I have a model called Patientinformation.php and a model called AlternativeInformation.php. I would like to use the two models in the patientinformation_form.php
Patientinformation model:
- id (PK)
- patient_id
- patient_initials
- collection_site
- cancer
- study (FK to study model)
AlternativeInformation model:
- alternative_id (PK)
- patients_patient_id (FK to id of the Patientinformation model)
- alternative_study (FK to study model)
- alternative_patient_id
I have updated the Patientinformation controller as well as the create.php file and the _form.php file.
If I enter values in the Patientinformation form.php, I am redirected to the Patientinformation view site. The values of the Patientinformation model (id, patient_id, patient_initials, collection_site, cancer and study) are saved in the database. However, the values of the AlternativeInformation model (alternative_study and alternative_patient_id) are not saved in the database.
This is the PatientinformationController.php file:
<?php
namespace app\controllers;
use Yii;
use app\models\Patientinformation;
use app\models\AlternativeInformation;
use app\models\PatientinformationSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* Creates a new Patientinformation model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post()) && $modelAlternative->load(Yii::$app->request->post())){
$model->save();
$modelAlternative->patients_patient_id = $model->id;
$modelAlternative->save();
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}
This is the create.php file:
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model app\models\Patientinformation */
/* #var $modelAlternative app\models\AlternativeInformation */
$this->title = 'Add patient';
$this->params['breadcrumbs'][] = ['label' => 'Patients', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="patientinformation-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]) ?>
</div>
And this is the _form.php file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use app\models\CollectionSiteInformation;
use app\models\AlternativeInformation;
use app\models\StudyInformation;
use app\models\CancerInformation;
use unclead\multipleinput\MultipleInput;
use kartik\select2\Select2;
/* #var $this yii\web\View */
/* #var $model app\models\Patientinformation */
/* #var $modelAlternative app\models\AlternativeInformation */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="patientinformation-form">
<?php $form = ActiveForm::begin(); ?>
<p>
Please note that all fields marked with an asterisk (<font color="red">*</font>) are required.
</p>
<?= $form->field($model, 'study')->widget(Select2::classname(), [
'data' => ArrayHelper::map(StudyInformation::find()->all(),'id','study'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a study'],
]);
?>
<?= $form->field($model, 'patient_id')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'patient_initials')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'collection_site')->widget(Select2::classname(), [
'data' => ArrayHelper::map(CollectionSiteInformation::find()->all(),'id','collection_site'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a collection site'],
]);
?>
<?= $form->field($model, 'cancer')->widget(Select2::classname(), [
'data' => ArrayHelper::map(CancerInformation::find()->all(),'id','cancer'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a cancer type'],
]);
?>
<?= $form->field($modelAlternative,'alternative_study')->widget(MultipleInput::class,[
'max' => 6,
'allowEmptyList' => false,
'enableGuessTitle' => true,
'columns' => [
[
'name' => 'alternative_study',
'type' => 'dropDownList',
'title' => 'Alternative Study',
'items' => ArrayHelper::map(studyInformation::find()->asArray()->all (),'id','study'),
'options' => ['prompt' => 'Please select an alternative study if applicable'],
],
]
])
->label(false);
?>
<?= $form->field($modelAlternative,'alternative_patient_id')->widget(MultipleInput::class,[
'max' => 6,
'allowEmptyList' => false,
'enableGuessTitle' => true,
'columns' => [
[
'name' => 'alternative_patient_id',
'title' => 'Alternative patient ID',
'options' => ['prompt' => 'Please select an alternative study if applicable'],
],
]
])
->label(false);
?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
If I don`t use unclead\multipleinput\MultipleInput in my _form.php, all the values of AlternativeInformation model (alternative_study and alternative_patient_id) are saved into the model/database.
So I assume that I don`t pass any items to the MultipleInput widget.
This is the AlternativeInformation model file:
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['patients_patient_id', 'alternative_study'], 'required'],
[['patients_patient_id', 'alternative_study'], 'integer'],
[['alternative_patient_id'], 'string', 'max' => 265],
[['patients_patient_id'], 'exist', 'skipOnError' => true, 'targetClass' => PatientInformation::className(), 'targetAttribute' => ['patients_patient_id' => 'id']],
[['alternative_study'], 'exist', 'skipOnError' => true, 'targetClass' => StudyInformation::className(), 'targetAttribute' => ['alternative_study' => 'id']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'alternative_id' => 'Alternative ID',
'patients_patient_id' => 'Patients Patient ID',
'alternative_study' => 'Alternative Study',
'alternative_patient_id' => 'Alternative Patient ID',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPatientsPatient()
{
return $this->hasOne(PatientInformation::className(), ['id' => 'patients_patient_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getAlternativeStudy()
{
return $this->hasOne(StudyInformation::className(), ['id' => 'alternative_study']);
}
}
Does anyone have any suggestions how this issue can be solved? How will be the values of "alternative_study" and "alternative_patient_id" saved into the AlternativeInformation model if using the MultipleInput widget?
I really need the option in the form to enter no, one or several alternative studies as well as alternative patient ids.
I really appreciate any help how I can solve this issue.
Thanks :)
You are probably getting some validation errors that you can't see because you are redirecting to the view action even if the AlternativeInformation model has validation errors.
The first step towards finding a solution would be making sure that, if AlternativeInformation doesn't save you show the form again, that way you will see the validation errors.
Update your controller code to this:
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post())
&& $modelAlternative->load(Yii::$app->request->post())
&& $model->save()) {
$modelAlternative->patients_patient_id = $model->id;
if ($modelAlternative->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}
That should help you find the problem, it will also give your users information about any future errors that may happen.
The validation problem may be on alternative_patient_id, it seems that you are not passing any items to the MultipleInput widget.
Update your controller with the following code.
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post()) && $modelAlternative->load(Yii::$app->request->post())){
if($model->save()){
$modelAlternative->patients_patient_id = $model->id;
$modelAlternative->save();
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}

Yii2 Codeception Functional tests - Click on OK button of confirm dialog

I'm a newer in Yii2 and programming tests.
I'm using Codeception for testing.
Summary:
In one of my tests I have to click on OK button of a confirm dialog. In order to do this, I have tried:
$I->click('OK');
$I->acceptPopup();
Neither of them work.
Details:
I'm using ActiveRecord to deal with a table of products ('productos'), and I used Gii to generate scripts.
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "productos".
*
* #property int $id
* #property string $codigo
* #property string $descripcion
* #property double $cantidad
* #property double $precio
* #property string $fefecto
*
* #property DetallesPedido[] $detallesPedidos
*/
class Productos extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'productos';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['codigo', 'descripcion', 'precio', 'fefecto'], 'required'],
[['cantidad', 'precio'], 'number'],
[['fefecto'], 'date', 'format'=>'yyyy-M-d'],
[['fefecto'], 'safe'],
[['codigo'], 'string', 'max' => 10],
[['descripcion'], 'string', 'max' => 60],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'codigo' => 'Codigo',
'descripcion' => 'Descripcion',
'cantidad' => 'Cantidad',
'precio' => 'Precio',
'fefecto' => 'Fecha Alta',
];
}
}
The script for the view asociated to Productos.php is:
use yii\helpers\Html;
use yii\widgets\DetailView;
/* #var $this yii\web\View */
/* #var $model app\models\Productos */
$this->title = $model->id . ' - ' . $model->codigo;
$this->params['breadcrumbs'][] = ['label' => 'Productos', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="productos-view">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= 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',
],
]) ?>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'codigo',
'descripcion',
'cantidad',
'precio',
'fefecto',
],
]) ?>
</div>
The script for functional test:
<?php
use app\models\Productos;
class ProductosCest
{
public function _before(\FunctionalTester $I)
{
//Deleting all products from database
Productos::deleteAll();
$I->amLoggedInAs(100);//Logarse
$I->amOnRoute('productos/index');
// Loading product on database
$I->haveRecord(Productos::className(), [
'id' => 1,
'codigo' => 'PA01',
'descripcion' => 'Paleta de acero triangular de 20 cm',
'cantidad' => 1,
'precio' => 10.53,
'fefecto' => '2017-03-12',
]);
}
public function _after(\FunctionalTester $I)
{
$I->click(['class' => 'btn-link']);//Logout
//Deleting all products from database
Productos::deleteAll();
}
public function deleteProducto(\FunctionalTester $I)
{
$I->amGoingTo('delete a product');
$I->amOnRoute('productos/delete', ['id' => 1]); //Click delete button from id=1
//Pulsar el botón Aceptar
/*
$I->performOn('.confirm', \Codeception\Util\ActionSequence::build()
->see('Are you sure you want to delete this item?')
->click('Aceptar')
);
*/
$I->acceptPopup();
$I->expect('be in the index product view');
$I->see('Productos', 'h1');
$I->expect('the product is not in the index product view');
$I->dontSee('Paleta de acero triangular de 20 cm');
}
}
When I run tests, I get:
There was 1 failure:
1) ProductosCest: Delete producto
Test tests/functional/ProductosCest.php:deleteProducto
Step Click {"class":"btn-link"}
Fail Link or Button by name or CSS or XPath element with class 'btn-link' was not found.
Scenario Steps:
$I->click({"class":"btn-link"}) at tests/functional/ProductosCest.php:28
$I->amOnRoute("productos/delete",{"id":1}) at tests/functional/ProductosCest.php:132
// I am going to delete a product
$I->haveRecord("app\models\Productos",{"id":1,"codigo":"PA01","descripc...}) at tests/functional/ProductosCest.php:17
$I->amOnRoute("productos/index") at tests/functional/ProductosCest.php:13
$I->amLoggedInAs(100) at tests/functional/ProductosCest.php:12
As you can see, there is a problem in line:
$I->acceptPopup();
because message 'be in the index product view' does not appear in the test log.
Screenshots:
View products
Confirm Dialog
You use Yii2 module in functional tests, right?
This module does not execute javascript code, so you won't get confirmation dialog.
In order to test confirmation dialog, you must use WebDriver module, which is used in acceptance suite usually.
acceptPopup method only works with native popup windows, as created by window.alert, window.confirm or window.prompt.
If you use a modal window (it looks like you do), you must use click method to click it.

Activeform data submit in database using Yii2, Not working

I m new in yii2 framework, when I submit my Activeform data to save in database in display error
Not Found (#404).
This Activeform mention in different model view. My form is on product page and I want just give review of customer regarding this product and save in DB.
view file: detail.php:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\widgets\ActiveForm;
/* #var $this yii\web\View */
/* #var $model app\models\Product */
$name = $result->name;
$price = $result->price;
$offerrate = 8;
$offer = ($price / 100) * $offerrate;
$offerprice = number_format($price - $offer, 2);
$text = $result->Description;
$list = explode(",", $text);
?>
<div id="page-content" class="home-page">
<div class="container">
<div class="row">
<div class="col-lg-5">
<center>
<?= Html::img(Yii::$app->urlManagerBackend->BaseUrl.'/'.$result->image, ['alt'=>'myImage','width'=>'300','height'=>'300', 'class' => 'img-responsive']) ?>
<br/>
<?= Html::button('ADD TO CART', ['class' => 'btn btn-success', 'id'=>'addcart']) ?>
<?= Html::button('BUY NOW', ['class' => 'btn btn-danger', 'id'=>'buynow']) ?>
</center>
</div>
<div class="col-lg-7">
<?php echo "<h5 style='color:#009933'>".$name."</h5>"?><br/>
<?php
echo "<ul>";
foreach ($list as $lists)
{
echo "<li class='liststyle'>".$lists."</li>";
}
echo "</ul>";
?><br/>
<?php echo "<h6 style='color:#009933'>MobileShop Offer Price Rs: ".$offerprice."</h6>" ?>
<?= Html::button('Rate and Review product', ['class' => 'btn btn-default', 'id'=>'review', 'data-toggle' => 'collapse', 'data-target' => '#demo']) ?>
<div id="demo" class="collapse">
<?php $form = ActiveForm::begin(['id' => 'reviewForm', 'action' => Yii::$app->urlManager->createUrl(['TblFeedback/create'])]); ?>
<?= $form->field($feedback, 'cust_name')->textInput() ?>
<?= $form->field($feedback, 'feedback')->textArea(['rows' => '2', 'cols' => '10'])?>
<?= $form->field($feedback, 'rating')->dropDownlist(['1' => '*', '2' => '* *', '3' => '* * *', '4' => '* * * *', '5' => '* * * * *']) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['id' => 'savebtn', 'class' => 'btn btn-default']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
</div>
</div>
Controller file: TblFeedbackController.php
<?php
namespace frontend\controllers;
use Yii;
use app\models\TblFeedback;
use frontend\models\Product;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
class TblFeedbackController extends \yii\web\Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
public function actionIndex()
{
return $this->render('index');
}
public function actionCreate()
{
$feedback = new TblFeedback();
if ($feedback->load(Yii::$app->request->post()) && $feedback->validate())
{
var_dump($feedback);
die();
$feedback->save();
Yii::$app->session->setFlash('success', '<h5>Thanks for review!</h5>');
return $this->redirect(['index']);
}
else {
return $this->render('index',
['feedback' => $feedback,
]);
Yii::$app->session->setFlash('error', 'Error Found!');
}
}
}
model file: TblFeedback.php
<?php
namespace frontend\models;
use Yii;
/**
* This is the model class for table "tbl_feedback".
*
* #property integer $id
* #property integer $product_id
* #property integer $cust_id
* #property string $cust_name
* #property integer $rating
* #property string $feedback
*
* #property Product $product
* #property User $cust
*/
class TblFeedback extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'tbl_feedback';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['product_id', 'cust_id', 'cust_name', 'rating', 'feedback'], 'required'],
[['product_id', 'cust_id', 'rating'], 'integer'],
[['rating'], 'integer', 'min' => 1, 'max' => 5],
[['cust_name'], 'string', 'max' => 200],
[['feedback'], 'string', 'max' => 1000],
[['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'id']],
[['cust_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['cust_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'product_id' => 'Product ID',
'cust_id' => 'Cust ID',
'cust_name' => 'Enter Name:',
'rating' => 'Rating',
'feedback' => 'Description',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getProduct()
{
return $this->hasOne(Product::className(), ['id' => 'product_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getCust()
{
return $this->hasOne(User::className(), ['id' => 'cust_id']);
}
}
The naming convention for controller action are based on - separator when a part is uppercase so you should use
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Yii::$app->urlManager->createUrl(['Tbl-feedback/create'])]); ?>
the naming convention,for the controllers, it is to start with a lowercase character.
so you should use
class tblFeedbackController extends \yii\web\Controller
and
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Yii::$app->urlManager->createUrl(['tbl-feedback/create'])]); ?>
and last suggestion you could use urlHelper
use yii\helpers\Url;
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Url::to(['tbl-feedback/create'])]); ?>

Dynamic forms operations with data on generated forms? yii2

basically. I have a problem with 2 things:
I'm using dynamic forms, the user can add as many as he needs to input all of the invoices at hand. I have a field (invoice_loadamount), i want to sum all of the invoice_loadamount fields. So if the user generates 3 forms i want it to sum dynamic form one(invoice_loadamount field 1) + dynamic form two.(invoice_loadamount field 2) + dynamic form three(invoice_loadamount field 3). How can i make this? Auto sum this field from every form he generated?
My second problem is that i want to then retrieve data from a table (vehicles, column vehicle_capacity) and then compare in such a way that it will validate if the sum is greater than the vehicle_maxcap and then give an error if so.
My form:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use wbraganca\dynamicform\DynamicFormWidget;
use app\models\Drivers;
use app\models\Vehicles;
use app\models\Invoices;
use dosamigos\datepicker\DatePicker;
use kartik\select2\Select2;
use yii\bootstrap\Modal;
use yii\helpers\Url;
/* #var $this yii\web\View */
/* #var $model app\models\Archive */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="archive-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']); ?>
<?= $form->field($model, 'driver_identitynum')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Drivers::find()->all(),'driver_identitynum', 'fullname'),
'language' => 'en',
'options' => ['placeholder' => 'Ingrese el numero de cedula...'],
'pluginOptions' => [
'allowClear' => true],
]); ?>
<div align="right"><?= Html::a('Add driver', ['/drivers/create'],
['target'=>'_blank']); ?>
</div>
<?= $form->field($model, 'vehicle_lp')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Vehicles::find()->all(),'vehicle_lp', 'fulltruck'),
'language' => 'en',
'options' => ['placeholder' => 'Ingrese la placa del vehiculo...'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
<div align="right"><?= Html::a('Add vehicle', ['/vehicles/create'],
['target'=>'_blank']); ?>
</div>
<div class="row"> <div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i>Facturas</h4></div>
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 4, // the maximum times, an element can be cloned (default 999)
'min' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsInvoices[0],
'formId' => 'dynamic-form',
'formFields' => [
'invoice_number',
'invoice_loadamount',
'invoice_date',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsInvoices as $i => $modelInvoices): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">Facturas</h3>
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<?php
// necessary for update action.
if (! $modelInvoices->isNewRecord) {
echo Html::activeHiddenInput($modelInvoices, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_number")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_loadamount")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-6">
<?= $form->field($modelInvoices, "[{$i}]invoice_date", ['enableAjaxValidation' => true])->widget(DatePicker::className(), [
// inline too, not bad
'inline' => false,
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'options' => ['class' => 'form-control picker'],
'clientOptions' => [
'autoclose' => true,
'format' => 'dd-mm-yyyy'
]
]);?>
</div>
</div><!-- .row -->
<div class="row">
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
My archive model:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "archive".
*
* #property integer $id
* #property string $driver_identitynum
* #property string $vehicle_lp
* #property string $DateCreated
*
* #property Invoices[] $invoices
*/
class Archive extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'archive';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['driver_identitynum', 'vehicle_lp'], 'required'],
[['DateCreated'], 'safe'],
[['driver_identitynum', 'vehicle_lp'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'driver_identitynum' => 'Cedula del conductor:',
'vehicle_lp' => 'Placa del vehiculo:',
'DateCreated' => 'Date Created',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getInvoices()
{
return $this->hasMany(Invoices::className(), ['archive_id' => 'id']);
}
}
My vehicle model:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "vehicles".
*
* #property integer $vehicle_id
* #property string $vehicle_model
* #property string $vehicle_lp
* #property string $vehicle_maxcap
*/
class Vehicles extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'vehicles';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['vehicle_model', 'vehicle_lp', 'vehicle_maxcap'], 'required'],
[['vehicle_model', 'vehicle_lp', 'vehicle_maxcap'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'vehicle_id' => 'Vehicle ID',
'vehicle_model' => 'Vehicle Model',
'vehicle_lp' => 'Vehicle Lp',
'vehicle_maxcap' => 'Vehicle Maxcap',
];
}
public function getfullTruck()
{
return $this->vehicle_lp.' - '.$this->vehicle_model.' - '.$this->vehicle_maxcap.'kgs';
}
}
My invoice model:
<?php
namespace app\models;
use Yii;
use yii\db\Query;
/**
* This is the model class for table "invoices".
*
* #property integer $id
* #property string $invoice_number
* #property string $invoice_loadamount
* #property string $invoice_date
* #property integer $archive_id
* #property string $DateProcessed
*
* #property Archive $archive
*/
class Invoices extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'invoices';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['invoice_number', 'invoice_loadamount', 'invoice_date'], 'required'],
[['archive_id'], 'integer'],
[['DateProcessed'], 'safe'],
//[['invoice_date'],'date','format'=>'dd-mm-yyyy','min'=>date('d-m-Y',time()-60*60*24*5)],
//Checks if invoice date put in is older than 5 days
[['invoice_date'], 'date', 'format'=>"dd-MM-yyyy", 'min'=>date("d-m-Y",strtotime('-5 days'))],
[['invoice_number', 'invoice_loadamount', 'invoice_date'], 'string', 'max' => 100]];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'invoice_number' => 'Numero de factura:',
'invoice_loadamount' => 'Carga de la factura(kgs):',
'invoice_date' => 'Fecha de emision de la factura:',
'archive_id' => 'Archive ID',
'DateProcessed' => 'Fecha de registro:'];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getArchive()
{
return $this->hasOne(Archive::className(), ['id' => 'archive_id']);
}
public function compareweight($attribute,$params)
{
$inputlp=($this->invoice_loadamount);
$row = (new \yii\db\Query())
->select('vehicle_lp')
->from('vehicles')
->where("vehicle_lp=$vehiclelp")
->all();
}
}
My controller:
<?php
namespace app\controllers;
use Yii;
use app\models\Vehicles;
use app\models\VehiclesSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* VehiclesController implements the CRUD actions for Vehicles model.
*/
class VehiclesController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
/**
* Lists all Vehicles models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new VehiclesSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Vehicles model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Vehicles model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Vehicles();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->vehicle_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Vehicles model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->vehicle_id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Vehicles model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Vehicles model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Vehicles the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Vehicles::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
As you can see from the HTML <input type="text" id="invoices-0-invoice_loadamount" class="form-control" name="Invoices[0][invoice_loadamount]" maxlength="100"> the loadamount input field is like this. So on the controller side either create function or update function will receive post data as $_POST['Invoices'] as an array like
array(
"0"=>array("invoice_number" => "132412", "invoice_loadamount" =>"34.00", "invoice_date" =>"2015-03-04"),
"1"=>array("invoice_number" => "352223", "invoice_loadamount" =>"233.00", "invoice_date" =>"2016-03-04"),
...
);
where 0, 1 represents each form added. In your case form one, form two etc.
What you need to do is just loop through the array you get from the array. Like this:
if (Yii::$app->request->isPost) {
$data = Yii::$app->request->post();
$invoices = $data['Invoices'];
$total = 0;
if(sizeof($invoices) > 0){
foreach($invoices as $one_invoice){
$one_loadamount = floatval($one_invoice['invoice_loadamount']);
$total += $one_loadamount;
}
}
//then you get the total amount as $total
}
for problem 2, you can then (assume that you already have the vehicle_id).
$vehicle = Vehicles::find()->where(['id'=>$vehicle_id])->one();
if($total > $vehicle->maxcap){
\Yii::$app->getSession()->setFlash('danger', 'Total is larger than max cap');
}
Since the second problem depends on a specific vehicles, you need to get its id first.

image are save in folder but not saved in database in yii2.0

i am new in yii and i use to upload images in databse but images are stored in folder but not saved in database what is the problem with this code coud not undurstand
public function actionCreate()
{
$model = new Jobs;
// $site_url=Yii::$app->getUrlManager()->createAbsoluteUrl('');
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$image = UploadedFile::getInstance($model,'image');
$imagepath='upload/jobs/';
$path=$imagepath.rand(10,100).$image->name;
if(!empty($image)){
$image->saveAs($path);
$model->image=$image->name;
$model->save();
}
return $this->redirect(['view', 'id' => $model->id]);
}
else {
// echo "file not ulpoaded";
}
return $this->render('create', [
'model' => $model,
]);
}
model is here named as Jobs.php.
namespace app\models;
use Yii;
use yii\web\UploadedFile;
use yii\base\Model;
/**
* This is the model class for table "jobs".
*
* #property integer $id
* #property integer $users_id
* #property string $title
* #property string $deadline
* #property string $urgency
*/
class Jobs extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*
*
*/
public $image;
public static function tableName()
{
return 'jobs';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['users_id', 'title', 'deadline', 'urgency'], 'required'],
[['users_id'], 'integer'],
[['content'], 'string'],
[['deadline'], 'required'],
[['urgency'], 'string'],
[['urgency'], 'safe'],
[['image'],'file', 'skipOnEmpty'=>true,'extensions' => 'png,gif,jpg'],
[['title'], 'string', 'max' => 255]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'users_id' => Yii::t('app', 'Users ID'),
'content'=>Yii::t('app','Content'),
'title' => Yii::t('app', 'Title'),
'deadline' => Yii::t('app', 'Deadline'),
'urgency' => Yii::t('app', 'Urgency'),
'image' => Yii::t('app', 'image'),
];
}
}
the view file is here named as (_form.php)
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\web\UploadedFile;
//use kartik\widgets\FileInput;
/* #var $this yii\web\View */
/* #var $model app\models\Jobs */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="jobs-form">
<?php
$form = ActiveForm::begin([
'options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'users_id')->textInput() ?>
<?= $form->field($model, 'content')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'deadline')->textInput() ?>
<?= $form->field($model, 'urgency')->dropDownList([ 'No', 'yes', ], ['prompt' => '']) ?>
<?= $form->field($model, 'image')->fileInput() ?>
<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>
enter code here
plzz help me to upload the image in database i dont know what the problem with this code.
change your upload code like below:
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$image = UploadedFile::getInstance($model,'image');
$imagepath='upload/jobs/';
$rand_name=rand(10,100);
if ($image)
{
$model->image = "category_{$rand_name}-{$image}";
}
if($model->save()):
if($image):
$image->saveAs($imagepath.$model->image);
endif;
endif;
return $this->redirect(['view', 'id' => $model->id]);
}
You're mixing image name and image file in your code.
public $imageis unnecessary if image is a field in your db-table. Instead add public $imageFile in your model, and update your form and controller accordingly.
Remember, $this->image, or $model->image is the name of the image as a string, you're mixing in an upload object. Instead create another variable so you can store the uploaded image in, and use the image variable for saving the actual name for later reference.
See if you can figure it out, and update your question if you can't get it to work.
http://www.yiiframework.com/doc-2.0/guide-input-file-upload.html