yii2 Dimensions to be validated and display the error message in the form - error-handling

In yii2 project I have my own file structure setup. Anything uploaded will get saved as a file type. I can get the file dimensions using the file uploaded in the temp folder by yii2. Using those dimensions I set my own width and height and compare them. If the height and width is more than what I have declared It has display an error message in the form. Which I am unable to do it.
My Active Form
<div class="company-form">
<?php
$form = ActiveForm::begin([
'action'=>['company/logo', 'id'=>$model->company_id],
'validateOnSubmit' => true,
'options' =>
['enctype' => 'multipart/form-data','class' => 'disable-submit-buttons','id'=> 'companyLogoForm'],
'fieldConfig' => [
'template' => "<div class=\"row\">
<div class=\"col-xs-6 margin-top-8\">{label}</div>\n<div class=\"col-xs-6 text-right\">{hint}</div>
\n<div class=\"col-xs-12 \">{input}</div>
</div>",
],
]); ?>
<?= $form->errorSummary($model, $options = ['header'=>'','class'=>'pull-left']); ?>
<?= $form->field($model, 'company_name')->hiddenInput(['maxlength' => true])->label(false) ?>
<?= $form->field($file, 'file')->fileInput([])->label(Yii::t('app', 'Attach Logo'),['class'=> 'margin-top-8']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Save') : Yii::t('app', 'Save'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','data' => ['disabled-text' => 'Please Wait']]) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
My Controller Action
public function actionLogo($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$file = new File;
$file->load(Yii::$app->request->post());
$a = UploadedFile::getInstance($file,'file');
$size = getimagesize($a->tempName);
$maxWidth = 500;
$maxHeight = 500;
if ($size[0] > $maxWidth || $size[1] > $maxHeight)
{
$model->addError('file', $error = 'Error Message');
if($model->hasErrors()){
return ActiveForm::validate($model);
}
}
$file->file = UploadedFile::getInstance($file,'file');
$file->file_name = $file->file->name;
$file->file_user = Yii::$app->user->id;
$file->file_type = 1;
if($file->save()){
$file->file_path = Files::getFilePath($file->file_id);
$validDir = $file->file->createFileDir($file->file_path, $file->file_id);
if($validDir){
$file->file->saveAs($file->file_path, false);
if($file->save()){
$model->company_file = $file->file_id;
$model->save();
return $this->redirect(['index']);
}
}
}
}
}
How do I add error message in the controller and pass that to display on my form on the modal box.
Note: my form is displayed on the modal box.
Thank you!!

You should handle the file processing in your model - or even better, create a specific UploadForm model for this purpose.
In that case you can use File Validation or a custom validator to set errors during model validation.
The built-in yii\validators\FileValidator gives you plenty pf validation rules out of the box.
This is actually pretty well explained in the documentation: Uploading Files
See also the documentation for FileValidator
Example for validating an uploaded image file:
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* #var UploadedFile
*/
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}

Try this validation rule
['imageFile', 'image', 'minWidth' => 250, 'maxWidth' => 250,'minHeight' => 250, 'maxHeight' => 250, 'extensions' => 'jpg, gif, png', 'maxSize' => 1024 * 1024 * 2],

Related

sending a text data between template to controller in cakephp 3

Definition :
I want to send text data from the template (ctp file) to the controller but it is not working.
What I DO Until now :
I have this controller courses and it has function called search as following :
/src/Controller/CoursesController :
public function search()
{
$search = $this->request->getData('keyword');
debug($search);die;
...
The /src/Template/search:
<?= $this->Form->create(null, ['url' => ['controller'=>'courses','action' => 'search']]) ?>
<?= $this->Form->control('keyword', ['label' => false, 'type'=>'text','class'=>'form-control', 'placeholder' => __('Search for...')]); ?>
<?= $this->Form->button(__('Go'), ['class' => 'btn btn-default', 'type' => 'submit']) ?>
<?= $this->Form->end() ?>
Despite my attempts to get the text data from the form and print it using debug but unfortunately I've got empty array
try this:
public function search()
{
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put', 'get']))
{
$search = $this->request->data('keyword');
debug($search);
}
}

Why i getting an error "Call to a member function formName() on a non-object"

i try to save multilanguaged content
My About model
...
public function rules() {
return [
[['status', 'date_update', 'date_create'], 'integer'],
[['date_update', 'date_create'], 'required'],
];
}
...
public function getContent($lang_id = null) {
$lang_id = ($lang_id === null) ? Lang::getCurrent()->id : $lang_id;
return $this->hasOne(AboutLang::className(), ['post_id' => 'id'])->where('lang_id = :lang_id', [':lang_id' => $lang_id]);
}
My AboutLang model
public function rules()
{
return [
[['post_id', 'lang_id', 'title', 'content'], 'required'],
[['post_id', 'lang_id'], 'integer'],
[['title', 'content'], 'string'],
];
}
My About controller
public function actionCreate()
{
$model = new About();
$aboutLang = new AboutLang();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,'aboutLang'=>$aboutLang]);
}
}
and my view (create form)
...
<?= $form->field($model, 'status')->textInput() ?>
<?= $form->field($aboutLang, 'title')->textInput() ?>
<?= $form->field($aboutLang, 'content')->textInput() ?>
enter code here
And when i put $aboutLang in create form i get an error "Call to a member function formName() on a non-object"
It looks like the views you are using were generated by Gii. In that case, Gii generates a partial view for the form (_form.php) and two views both for create and update actions (create.php and update.php). These two views perform a rendering of the partial view.
The problem you might have is that you are not passing the variable $aboutLang from create.php to _form.php, that must be done in create.php, when you call renderPartial():
$this->renderPartial("_form", array(
"model" => $model,
"aboutLang" => $aboutLang, //Add this line
));
Hope it helps.
Check your $aboutLang type.
It looks like it is null.
if ($aboutLang) {
echo $form->field($aboutLang, 'title')->textInput();
echo $form->field($aboutLang, 'content')->textInput();
}

Yii2: Images stored in different tables

Here my controller:
$model = new VehicleType();
if ($model->load(Yii::$app->request->post())) {
if($model->validate()){
$model->save();
$id = $model->id;
$model->file = UploadedFile::getInstance($model, 'file');
if($model->file){
$id = $model->id;
$imageName = "vehicletype_".$id.'_'.getdate()[0];
$model->file->saveAs('uploads/'.$imageName.'.'.$model->file->extension);
$station = VehicleType::findOne($id);
$station->image = '#web/uploads/'.$imageName.'.'.$model->file->extension;
$station->save();
}
return $this->redirect(['vehicletype/index']);
}
} else {
return $this->renderAjax('create', [
'model' => $model,
]);
}
}
My view:
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'station-form', 'options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'description')->textarea() ?>
<?= $form->field($model, 'file')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
My model:
public function rules()
{
return [
[['description'], 'string'],
[['record_status'], 'integer'],
[['name', 'image'], 'string', 'max' => 255]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => 'Name',
'description' => 'Description',
'image' => 'Image',
'record_status' => 'Record Status',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getVehicles()
{
return $this->hasMany(Vehicles::className(), ['vehicle_type_id' => 'id']);
}
}
With this I can upload only one picture/post, I want one post to have multiple pictures, so I create a new table call 'Image' to stored my pictures and have a one-to-many relationship.
But I run into a problem, how can I add data to 2 tables from just 1 form
I'm using Yii2 basic template
Thanks
Step 1
First create two variables in your vehicletype model.
public $uploadedImages;
public $imageforNewtable = array();
Step 2
Make sure to mention this imageforNewtable variable in your model rule.
[['imageforNewtable'], 'image', 'extensions' => 'png, jpg, JPEG'],
Step 3
In your form:
<?php $form = ActiveForm::begin(['id' => 'station-form', 'options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'imageforNewtable[]')->fileInput(['accept' => 'image/*']); ?>
Step 4
In Your Controller:
$model->uploadedImages = UploadedFile::getInstances($model,'imageforNewtable');
// Make sure to put "Instances" (plural of Instance) for uploading multiple images
$model->imageforNewtable = array(); // To avoid blank entries as we have entries in $_FILES not in $_POST.
foreach ($model->uploadedImages as $singleImage)
{
$model->imageforNewtable[] = time() . '_' . $singleImage->name;
}
Now bulk insert data in Images table :
$bulkInsertforimages = array(); //defined benchInsert array for images
$columnsArray = ['blog_id', 'image']; //Column names in which bulk insert will take place.
if ($model->imageforNewtable != '') {
foreach ($model->imageforNewtable as $singleData) {
$bulkInsertforimages[] = [
'blog_id' => $model->id,
'image' => $singleData,
];
}
}
if (count($bulkInsertforimages) > 0) {
$command = \Yii::$app->db->createCommand();
$command->batchInsert('YOUR_IMAGE_TABLE', $columnsArray, $bulkInsertforimages)->execute();
}

Upload multiple files yii2

Tell me where I was wrong, everything is tried
my view file:
echo FileInput::widget([
'model' => $model,
'attribute' => 'files[]',
'options' => ['multiple' => true]
]);
Also i added
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
enctype option to form element
Model:
i add two variables as property:
public $files; // files instance
public $serialize; // set string which store the files
in rules
serialize as string, and files:
[['files'], 'file', 'skipOnEmpty' => true, 'extensions' => 'gif, jpg, png, pdf, doc, docx', 'maxFiles' => 10],
and controller action:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$oldFiles = $model->serialize;
$files = UploadedFile::getInstance($model, 'files');
if($files === false){
$model->serialize = $oldFiles;
} else {
$serialize = [];
if($model->validate()){
foreach($files as $file){
$ext = end((explode(".", $file)));
$filename = Yii::$app->security->generateRandomString().".{$ext}";
$serialize[] = $filename;
$file->saveAs(Yii::$app->basePath . '/web/image/' . $filename);
}
} else {
}
//print_r($model->getErrors()); die();
$model->serialize = serialize($serialize);
}
$model->save();
return $this->redirect(['view', 'id' => $model->news_id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
So, $files is empty, why?
also i get a "4" code error in $_FILES array
It should be getInstances for multiple files.
$files = UploadedFile::getInstances($model, 'files');

`Skip on empty` not working in Yii2 file upload

I have a provision to upload logo for companies in my application. Uploading and saving on creating profile works fine. But on update, logo goes empty if I am not uploading it again!
Here's my update form
<?php $form = ActiveForm::begin([
'options' => ['enctype'=>'multipart/form-data']
]); ?>
.....
<?= $form->field($model, 'logo')->fileInput() ?>
...
My Controller action
if ($model->load($_POST) ) {
$file = \yii\web\UploadedFile::getInstance($model, 'logo');
if($file){
$model->logo=$file; }
if($model->save()){
if($file)
$file->saveAs(\Yii::$app->basePath . '/web/images/'.$file);
}
return $this->redirect(['profile']);
} else {
return $this->renderPartial('update', [
'model' => $model,
]);
}
My Rules:
public function rules()
{
return [
[['logo'], 'image', 'extensions' => 'jpg,png', 'skipOnEmpty' => true],
[['name'], 'required'],
[['name', 'description'], 'string'],
];
}
Any ideas????
skipOnEmpty does not apply here because in the update action the $model->logo attribute will not be empty, it will be a string with the file name.$file is still an array with only keys, but not values if not uploaded again. So checked the $file->size instead of checking !empty($file). Fixed the issue by modifying the controller code as follows!
$model = $this->findModel($id);
$current_image = $model->featured_image;
if ($model->load(Yii::$app->request->post())) {
$image= UploadedFile::getInstance($model, 'featured_image');
if(!empty($image) && $image->size !== 0) {
//print_R($image);die;
$image->saveAs('uploads/' . $image->baseName . '.' .$image->extension);
$model->featured_image = 'uploads/'.$image->baseName.'.'.$image->extension;
}
else
$model->featured_image = $current_image;
$model->save();
return $this->redirect(['update', 'id' => $model->module_id]);
} else {
return $this->render('add', [
'model' => $model,
]);
}
'skipOnEmpty' => !$this->isNewRecord
For update it can be skipped.