Either or validation for string and file yii2 - yii2

I have two fields message and file where one is just plain string and file is an image.
I want to create validator which only allows user to send either one of those 2 fields.
I tried when validator but in when the field $model->file is always null so what is other method to do either or validation with file.
Here is my model code
class Message extends \yii\db\ActiveRecord
{
public $file;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'message';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['sender_id', 'receiver_id'], 'integer'],
[['message'], 'string'],
[['file'], 'file', 'extensions'=>'jpg, gif, png,jpeg'],
/*['file', 'required', 'when' => function($model) {
return $model->message == null;
}],
['message', 'required', 'when' => function($model) {
return $this->file->baseName == null;
}]*/
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'sender_id' => 'Sender ID',
'receiver_id' => 'Receiver ID',
'message' => 'Message',
'file' => 'Image (jpg/png)',
'is_delivered' => 'Is Delivered',
'is_notified' => 'Is Notified',
'is_deleted' => 'Is Deleted',
'created_date' => 'Created Date',
'updated_date' => 'Updated Date',
'is_group' => 'Is Group',
];
}
}
Thank you

This may Help you..
Define Your rules as : -
public function rules()
{
return [
//Your Rules ......
['message' ,'string'],
['file' ,'file'],
['message', 'required', 'when' => function($model) {
return $model->file === null;
} ,'whenClient' => 'function (attribute, value) {
return $("#'. Html::getInputId($this ,'file') .'").val() === null;
}'],
['file', 'required', 'when' => function($model) {
return $model->message === null;
} , 'whenClient' => 'function (attribute, value) {
return $("#'. Html::getInputId($this ,'message') .'").val() == "";
}'],
];
}

Related

Yii2 - Update Complex Form

I created a Complex Form using two Model Classes:
Courses
CourseStructure
public function actionCreate()
{
$model = new Course();
$request = Yii::$app->request;
if ($model->load(Yii::$app->request->post()) && Yii::$app->request->isAjax) {
//The course was created successfully, so we can use its data to make course structure
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post())) {
$model->attributes = $_POST['Course'];
$model->course_start_date = date('Y-m-d', strtotime($_POST['Course']['course_start_date']));
$model->created_at = new \yii\db\Expression('NOW()');
}
$model->save(false);
if($model->save(false))
//The course was created successfully, so we can use its data to make course structure
{
// check if topic format
if($model->course_format == Course::TYPE_TOPIC)
{
for( $i = 1; $i <= $model->course_format_no; $i++ )
{
$structure = new CourseStructure();
$structure->course_id = $model->course_id;
$structure->structure_name = $model->course_format . $i;
$structure->structure_id = $i;
// fill in other course structure data here
$structure->save();
}
}
}
else
return $this->render('create', ['model' => $model,]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
From CourseControllers, if course_format = TYPE_TOPIC, then based on the course_format_no selected,
some rows are added in course_structure table (CourseStructure). For instance, if course_format_no = 3, it creates three additional rows in course_structure table.
if($model->course_format == Course::TYPE_TOPIC)
{
for( $i = 1; $i <= $model->course_format_no; $i++ )
{
$structure = new CourseStructure();
$structure->course_id = $model->course_id;
$structure->structure_name = $model->course_format . $i;
$structure->structure_id = $i;
// fill in other course structure data here
$structure->save();
}
}
It works fine in CourseCreate Action in CourseController.
Now how do I do it for the CourseUpdate Action, so that if that either reduce the number of rows or increase it in course_structure table based on the course_format_no added in the update.
course_structure
This is what I have:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$old_model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post())) {
$model->attributes = $_POST['Course'];
$model->course_start_date = Yii::$app->dateformatter->getDateFormat($_POST['Course']['course_start_date']);
$model->updated_by = Yii::$app->getid->getId();
$model->updated_at = new \yii\db\Expression('NOW()');
if($model->save(false))
return $this->redirect(['view', 'id' => $model->course_id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
CourseStructure model
class CourseStructure extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'course_structure';
}
public function rules()
{
return [
[['course_id', 'structure_id', 'summary_format', 'created_by', 'updated_by'], 'integer'],
[['structure_summary'], 'string'],
[['created_at', 'updated_at'], 'safe'],
[['structure_name'], 'string', 'max' => 200],
];
}
public function attributeLabels()
{
return [
'course_structure_id' => 'Course Structure ID',
'course_id' => 'Course ID',
'structure_id' => 'Structure ID',
'structure_name' => 'Structure Name',
'structure_summary' => 'Structure Summary',
'summary_format' => 'Summary Format',
'created_at' => 'Created At',
'created_by' => 'Created By',
'updated_at' => 'Updated At',
'updated_by' => 'Updated By',
];
}
public function getCourses()
{
return $this->hasOne(Course::className(), ['course_id' => 'course_id']);
}
public static function getAllCourseStructure()
{
$dataTmp = self::find()->orderBy('structure_name')->all();
$result = yii\helpers\ArrayHelper::map($dataTmp, 'course_structure_id', 'structure_name');
return $result;
}
}
Courses model
class Course extends \yii\db\ActiveRecord
{
const TYPE_WEEKLY= 'Weekly';
const TYPE_TOPIC='Topic';
public $coursefile;
public static function tableName()
{
return 'course';
}
public function rules()
{
return [
[['course_category_id', 'course_format_no', 'show_grade', 'created_by', 'updated_by'], 'integer'],
[['course_code', 'course_name', 'course_format', 'course_format_no'], 'required', 'message' => ''],
[['course_summary'], 'string'],
[['course_start_date', 'created_at', 'updated_at', 'course_file_path'], 'safe'],
[['course_code'], 'string', 'max' => 100],
[['course_name'], 'string', 'max' => 255],
[['course_num', 'course_format'], 'string', 'max' => 20],
[['course_code'], 'unique'],
[['coursefile'], 'safe'],
[['course_name', 'course_category_id'], 'unique', 'targetAttribute' => ['course_name', 'course_category_id'], 'message' => Yii::t('app', 'The combination of Course Name and Course Category has already been taken.')],
[['coursefile'], 'file', 'extensions' => 'jpg, jpeg, gif, png, pdf, txt, jpeg, xls, xlsx, doc, docx', 'maxFiles' => 4],
[['coursefile'], 'file', 'maxSize'=>'10000000'],
[['course_file_path', 'course_file_name'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{
return [
'course_id' => 'Course ID',
'course_category_id' => 'Course Category',
'course_code' => 'Course Short Name',
'course_name' => 'Course Full Name',
'course_num' => 'Course ID Number',
'course_summary' => 'Course Summary',
'course_start_date' => 'Course Start Date',
'course_format' => 'Course Format',
'course_format_no' => 'No.of Sections',
'course_file_path' => Yii::t('app', 'Pathname'), //'Course File',
'course_file_name' => Yii::t('app', 'Filename'),
'show_grade' => 'Show Grade',
'created_at' => 'Created At',
'created_by' => 'Created By',
'updated_at' => 'Updated At',
'updated_by' => 'Updated By',
];
}
public function getCourseCategory()
{
return $this->hasOne(CourseCategories::className(), ['course_category_id' => 'course_category_id']);
}
public static function getAllCourse()
{
$dataTmp = self::find()->orderBy('course_name')->all();
$result = yii\helpers\ArrayHelper::map($dataTmp, 'course_id', 'course_name');
return $result;
}
public static function getCourseFormat()
{
return[
Yii::t('app', self::TYPE_TOPIC) => Yii::t('app', 'Topic'),
Yii::t('app', self::TYPE_WEEKLY) => Yii::t('app', 'Weekly'),
];
}
}
How do I write the code to update CourseStructure in the ActionUpdate.

Yii2 MultilingualBehavior throws getPrimaryKey error

I want to save multilingual record in my table but some error occurs - Call to a member function getPrimaryKey() on string. I am using multilingual behavior
and it is not for first time. Made two tables system_information and system_informationLang. This is my model:
<?php
namespace app\models;
use backend\models\CActiveRecord;
use Yii;
use omgdef\multilingual\MultilingualBehavior;
use omgdef\multilingual\MultilingualQuery;
/**
* This is the model class for table "system_information".
*
* #property int $id
* #property int $city_id
*
* #property SystemInformationlang[] $systemInformationlangs
*/
class SystemInformation extends CActiveRecord
{
public static function find()
{
return new MultilingualQuery(get_called_class());
}
public function behaviors()
{
$allLanguages = [];
foreach (Yii::$app->params['languages'] as $title => $language) {
$allLanguages[$title] = $language;
}
return [
'ml' => [
'class' => MultilingualBehavior::className(),
'languages' => $allLanguages,
//'languageField' => 'language',
//'localizedPrefix' => '',
//'requireTranslations' => false',
//'dynamicLangClass' => true',
//'langClassName' => PostLang::className(), // or namespace/for/a/class/PostLang
'defaultLanguage' => Yii::$app->params['languageDefault'],
'langForeignKey' => 'system_id',
'tableName' => "{{%system_informationlang}}",
'attributes' => [
'name',
'email',
'phone',
'address',
'facebook',
'instagram',
'google',
'linkin',
'fax',
'owner',
'latitude',
'longitude'
]
],
];
}
/**
* #inheritdoc
*/
public static function tableName()
{
return 'system_information';
}
/**
* #inheritdoc
*/
public function rules()
{
$string_255_lang = $this->multilingualFields([
'name',
'email',
'phone',
'address',
'facebook',
'instagram',
'google',
'linkin',
'fax',
'owner',
'latitude',
'longitude'
]);
$string_255 = [
'name',
'email',
'phone',
'address',
'facebook',
'instagram',
'google',
'linkin',
'fax',
'owner',
'latitude',
'longitude'
];
$require = ['name', 'phone', 'email', 'owner', 'address'];
$email_lang = $this->multilingualFields(['email']);
$email = ['email'];
return [
[$require, 'required'],
[$string_255, 'string', 'max' => 255],
[$string_255_lang, 'string', 'max' => 255],
[['city_id'], 'integer'],
[$email_lang, 'email'],
['email', 'email'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'city_id' => Yii::t('app', 'City ID'),
];
}
}
This is custom function for language fields creating :
protected function multilingualFields($fields){
$output = [];
foreach ($fields as $field){
foreach (Yii::$app->params['languages'] as $language) {
if(Yii::$app->params['languageDefault'] != $language){
$output[] = "{$field}_{$language}";
}
}
}
return $output;
}
And finally my controller:
public function actionCreate()
{
$model = new SystemInformation();
if ($model->load(Yii::$app->request->post())) {
$model->multilingualLoad($model, [
'name',
'email',
'phone',
'address',
'facebook',
'instagram',
'google',
'linkin',
'fax',
'owner',
'latitude',
'longitude'
]);
var_dump($model->save());
var_dump($model->getErrors());die;
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}else{
Yii::$app->session->setFlash('error', Yii::t('app', 'Something went wrong. Please, try again later!'));
return $this->render('create', [
'model' => $model,
]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
multilingualLoad is also a custom function for filling the lingual fields:
public function multilingualLoad($model, $props = []){
$model_name = explode('\\', get_class($model));
$model_name = end($model_name);
foreach (Yii::$app->params['languages'] as $language){
if(Yii::$app->params['languageDefault'] != $language){
foreach ($props as $property){
$prop_lang = "{$property}_{$language}";
$model->$prop_lang = Yii::$app->request->post($model_name)["{$property}_{$language}"];
}
}
}
}
I got a picture of the Yii2 error. I guess it is searching for the lang table but somehow $owner gets value of a string.
Thank you in advance!

yii2 custom validation addError message doesn't show

when i use custom validations on yii2 dynamic forms it doesn't show any error messages below the input field.Below I have posted my model.
It doesn't show any error messges when qty field gets validated
namespace frontend\models;
use Yii;
class OrderD extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'order_d';
}
public function rules()
{
return [
[['item_id', 'qty', 'price', 'value'], 'required'],
[['item_id'], 'integer'],
[['price', 'value'], 'number'],
[['order_code'], 'string', 'max' => 10],
[['item_id'], 'exist', 'skipOnError' => true, 'targetClass' => Item::className(), 'targetAttribute' => ['item_id' => 'id']],
[['order_code'], 'exist', 'skipOnError' => true, 'targetClass' => OrderH::className(), 'targetAttribute' => ['order_code' => 'code']],
['qty', 'validateQty']
];
}
public function validateQty($attribute)
{
$qty = $this->$attribute;
if ($qty >= 5)
{
$this->addError('qty', "qty validation successful");
}
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'item_id' => 'Item ID',
'order_code' => 'Order Code',
'qty' => 'Qty',
'price' => 'Price',
'value' => 'Value',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getItem()
{
return $this->hasOne(Item::className(), ['id' => 'item_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getOrderCode()
{
return $this->hasOne(OrderH::className(), ['code' => 'order_code']);
}
}
Be sure to know custom validations are php functions and not convert as javascript to validate in runtime .. those will work after the page has submit and send to controller ..
here is simple sample you want :
['qty','custom_function_validation'],
];
}
public function custom_function_validation($attribute, $params){
if($this->$attribute>5){
$this->addError($attribute,'it\'s more than 5');
}
}
To create a validator that supports client-side validation, you should implement the yii\validators\Validator::clientValidateAttribute() method which returns a piece of JavaScript code that performs the validation on the client-side.
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
// your validation
JS;
}
See the documentation here: http://www.yiiframework.com/doc-2.0/guide-input-validation.html#implementing-client-side-validation
Use method addError() in a controller and then just render your view file
Example
if ($promo_code) {
if ($promo_code->status == '1') {
$message = 'This combination is incorrect.';
$model->addError('promo_code', $message);
return $this->render('index', compact('model'));
}
$promo_code->status = '1';
$promo_code->save();
$model->save();
}

Unable to save model attribute as null?

Here is my model rules
public function rules() {
return [
[['header_image', 'profil_picture'], 'default', 'value' => null],
[['yahoo_id', 'whats_app_id', 'bbm_id'], 'string', 'max' => 20],
[['bbm_id'], 'match', 'pattern' => '/^[a-zA-Z0-9]+$/', 'message' => 'Alpha numeric only'],
[['header_image_file', 'profil_picture_file'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpeg, jpg, bmp', 'maxSize' => 10240 * 20240 * 2],
[['deskripsi_toko'], 'string', 'max' => 300],
[['agent_id', 'nama_toko', 'tag_line', 'header_image', 'profil_picture', 'yahoo_id', 'whats_app_id', 'bbm_id', 'deskripsi_toko'], 'filter', 'filter' => function($value) {
return BeoHelper::replace_mc($value);
}],
];
}
Here is my controller
$storeSetting->header_image = null;
if($storeSetting->save()){
return $this->redirect(Yii::$app->request->referrer);
}
replace_mc function
public static function replace_mc($str)
{
$new_data = preg_replace('/[^A-Za-z0-9\-\ \.\:\#\+]/', '', $str);
return $new_data;
}
Record save successfully, but header_image is empty string instead of null?
It should set header_image as null, Where I'm doing wrong?
Thanks in advance.
Try with additional condition in replace_mc():
public static function replace_mc($str)
{
return $str === null
? $str
: preg_replace('/[^A-Za-z0-9\-\ \.\:\#\+]/', '', $str);
}

How to save current user_id to database (YII2)

I try to save current user_id to the education table in database. However,the data of user_id is not filled. This is my code.
At model
public function rules()
{
return [
[['year', 'fieldstudy', 'institute', 'grade'], 'required'],
[['user_id'], 'integer'],
[['year', 'fieldstudy', 'institute', 'grade'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{
return [
'education_id' => 'Education ID',
'user_id' => 'User ID',
'year' => 'Year',
'fieldstudy' => 'Fieldstudy',
'institute' => 'Institute',
'grade' => 'Grade',
];
}
public function getUser()
{
return $this->hasOne(User::className(), ['user_id' => 'user_id']);
}
At controller
public function actionCreate()
{
$model = new Education();
$model->user_id =Yii::$app->user->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->education_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
How can I solve my problem and fix my code? Thanks
update Yii::$app->user->id to Yii::$app->user->identity->id.
public function actionCreate()
{
$model = new Education();
if ($model->load(Yii::$app->request->post())) {
$model->user_id =Yii::$app->user->identity->id;
if($model->save()){
return $this->redirect(['view', 'id' => $model->education_id]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
You have to check two things
Check whether the user is logged in.
Use Yii2 debugger to see whether we are getting the id value of the logged in user by the code Yii::$app->user->id or Yii::$app->user->id
Use Yii2 debugger to check whether the correct user id value we are getting by using the code
Yii::info("User id=".Yii::$app->user->id);
Full code you have to try in the controller is given below
public function actionCreate() {
$model = new Education();
//checking whether we are getting the logged in user id value
Yii::info("User id=".Yii::$app->user->id);
$model->user_id = Yii::$app->user->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
//checking here the saved user id value in table
Yii::info("checking User id after saving model=".$model->user_id);
return $this->redirect(['view', 'id' => $model->education_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Now after running the application you can check using Yii2 debugger the values that are set in the user id in various places.