when i upload multiple files in Yii2, i am getting following error and cannot insert data into database:
finfo_file(C:\xampp\tmp\phpCACD.tmp): failed to open stream: No such
file or directory
controller file:
public function actionGallery($id)
{
$model = new Gallery();
if (Yii::$app->request->post()) {
$model->imageFiles = UploadedFile::getInstances($model,'imageFiles');
foreach ($model->imageFiles as $file) {
$imageName = Yii::$app->security->generateRandomString();
$model->added_date = date('Y-m-d');
$model->emp_id = $id;
$file->saveAs('uploads/emp/' . $imageName . '.' . $file->extension);
$originalFile = EMP_PROFILE_ORIGINAL.$imageName.'.'.$file->extension;
$thumbFile = EMP_PROFILE_THUMB.$imageName.'.'.$file->extension;
Image::thumbnail($originalFile, 200, 200)->save($thumbFile, ['quality' => 80]);
$model->save();
}
}
return $this->render('gallery', [
'gal' => $model
]);
}
view file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\grid\GridView;
?>
<div class="posts-form">
<div class="wrapper-md">
<div class="row">
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-body">
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($gal, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
<div class="form-group">
<button class="btn btn-success">Submit</button>
<a class="btn btn-default" href="<?=\Yii::$app->urlManager->createUrl('post')?>">Cancel</a>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
</div>
</div>
</div>
but i am getting above error. I cannot find the solution for this.
first, in model you must have 2 variable that will save the images and the name of it.
`
* #property string $image_name
*/
class Gallery extends \yii\db\ActiveRecord
{
**public $fileImage=[];**
public static function tableName(){
`
in this case I use $image_name that is one of my model column, and $fileImage, $fileImage is an array that will be used to upload the image,
:)
then in controller
$model = new Gallery(); // this variable is only used to check if everything is valid
if ($model->load(Yii::$app->request->post())) {
$model->fileImage = UploadedFile::getInstances($model,'fileImage');
$a=0;
foreach ($model->fileImage as $file) {
$a++;
$model1 = new Gallery();
$file->saveAs("images/test".$a.".".$file->extension);
$model1->image_url="images/test.".$a.".".$file->extension;
$model1->image_name = "".$a;
$model1->save();
}
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
I think thats all. . .
You can use
$sql = 'INSERT INTO `table`(`id`, `col1`, `col2`, `path`) VALUES (Null,"'.($model2->col1).'","'.($model2->col2).'","'.($model2->path).'")';
$command = \Yii::$app->db->createCommand($sql);
$command->execute();
instead of $model->save();
I made an example,
so the whole code in controller would be:
public function actionCreate()
{
$model = new Planet();
if ($model->load(Yii::$app->request->post()) ) {
$model->file = UploadedFile::getInstances($model, 'file');
foreach ($model->file as $file) {
$model2 = new Planet();
$model2->load(Yii::$app->request->post());
$model2->path='uploads/' . $file;
$sql = 'INSERT INTO `planet`(`id`, `name`, `s_id`, `path`) VALUES (Null,"'.($model2->name).'","'.($model2->s_id).'","'.($model2->path).'")';
$command = \Yii::$app->db->createCommand($sql);
$command->execute();
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
return $this->render('view', [
'model' => $model,
]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
It works for me.
edit: also you can use $model2->save(false); It worked in my case.
Call $model->save()
before
$model->file->saveAs();
I was having the exact same problem
*I think you forget to create uploads and emp folder or maybe you use wrong folder name, please check your folder name...
*If you want to save the name of that file, you should use different variable (two variable) that will be used to save the images and the name of that images,
Related
I am coding a form to get user input and then pass that information to a controller and execute a function based on that, at this point I can not pass the data to the controller using POST method, I get empty vars.
So the Controller function display the view form correctly, I can type on the textboxes, after press submit button I get a setFlash custom message that the parameters are empty. I am using a model class with just two parameters.
a) This is the model:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class SendmailForm extends Model
{
public $template;
public $emtransport;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['template', 'emtransport'], 'required'],
];
}
}
b) This is the view:
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
$this->title = 'Send Mail';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<?php if (Yii::$app->session->hasFlash('sminfo')): ?>
<div class="alert alert-success">
<?= Yii::$app->session->getFlash('sminfo');?>
</div>
<?php else: ?>
<p>
SendMail Exercise. Please choose needed options bellow:
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'sendmail-form']); ?>
<?= $form->field($model, 'template')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'emtransport') ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'value'=>'one', 'name'=>'sendbtn']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
<?php endif; ?>
</div>
And this is the controller's function:
public function actionSendmail(){
$model = new SendmailForm();
if ($model->load(Yii::$app->request->post())) {
$template = Yii::$app->request->post('template');
$emailTransport = Yii::$app->request->post("emtransport");
if($emailTransport=="local"){
for($i=0;$i<=2;$i++){
$xclient = 'client' . $i;
\app\models\User::findByUsername($xclient)->sendMail($template, 'Welcome To XYZ Services', ['accountInfo' => 'www.mysite.com']);
}//end of for loop
Yii::$app->session->setFlash("sminfo", "Emails sent successfully to the Clients");
return $this->refresh();
}//end of second if loop
else{
Yii::$app->session->setFlash("sminfo", "Params could not be verified!. Contact Tech Support");
return $this->refresh();
}
}//end of post if loop
return $this->render('sendmail', [
'model' => $model,
]);
}
The idea is to get the values from the view, at this moment I am getting empty values-
Two parts below:
$template = Yii::$app->request->post('template');
$emailTransport = Yii::$app->request->post("emtransport");
Change the following:
$template = $model->template;
$emailTransport = $model->emtransport;
After editing
public function actionSendmail(){
$model = new SendmailForm();
if ($model->load(Yii::$app->request->post())) {
$template = $model->template;
$emailTransport = $model->emtransport;
if($emailTransport=="local"){
for($i=0;$i<=2;$i++){
$xclient = 'client' . $i;
\app\models\User::findByUsername($xclient)->sendMail($template, 'Welcome To XYZ Services', ['accountInfo' => 'www.mysite.com']);
}//end of for loop
Yii::$app->session->setFlash("sminfo", "Emails sent successfully to the Clients");
return $this->refresh();
}//end of second if loop
else{
Yii::$app->session->setFlash("sminfo", "Params could not be verified!. Contact Tech Support");
return $this->refresh();
}
}//end of post if loop
return $this->render('sendmail', [
'model' => $model,
]);
}
I did some changes to the Controller and now it works, those are them:
//at the beginning of the Controller:
use app\models\SendmailForm;
//two lines changed in the function:
$model->template = $_POST['SendmailForm']['template'];
$model->emtransport = $_POST['SendmailForm']['emtransport'];
That's all I needed. Best regards
ERORR Undefined variable: listings
Users create a for sale advertising listing:
$listing->user_id = auth()->user()->id;
$listing->email= auth()->user()->email;
$listing->phone_number= auth()->user()->phone_number;
$listing->package = $request->session()->get('package');
$listing->save();
return view('user.dashboard');
After they get transferred to a dashboard page
#if($listings->isEmpty())
<div class="padding-top">
<h1 class="centre">None</h1>
</div>
#else
#endif
#foreach ($listings as $listing)
<div class="row">
<div class="container">
<div class="card">
<div class="card-body row">
<h5 class="card-title cardtitle col-lg-12 centre">{{$listing->address}}</h5>
incomplete html but just is an extract
EDIT ADDED FULL CONTROLLER Using return view('user.dashboard', ['listings' => $listing]); still throws an error
public function store(Request $request)
{
$this->validate($request, [
'image1' => 'image|nullable|max:1999',
'image2' => 'image|nullable|max:1999'
]);
// Handle File Upload
if($request->hasFile('image1')){
// Get filename with the extension
$filenameWithExt = $request->file('image1')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('image1')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('image1')->storeAs('public/cover_images', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$listing = new Listings;
$listing->user_id = auth()->user()->id;
$listing->email= auth()->user()->email;
$listing->phone_number= auth()->user()->phone_number;
$listing->package = $request->session()->get('package');
$listing->save();
$listing->image1 = $fileNameToStore;
return view('user.dashboard', ['listings' => $listing]);
}
Change
return view('user.dashboard');
into
return view('user.dashboard', compact('listing'));
I think the reason is pretty clear.
You need to pass $listing to your view like this:
return view('user.dashboard', compact('listing');
Edit:
Of course your variables must be named the same in your controller and view. You now have a mismatch as you name your variable $listing in your controller but call it as $listings in your view. Your code should be like this:
$listings->user_id = auth()->user()->id;
$listings->email= auth()->user()->email;
$listings->phone_number= auth()->user()->phone_number;
$listings->package = $request->session()->get('package');
$listings->save();
return view('user.dashboard', compact('listings');
Then you can call the variable as $listings in your view, so your view code doess not have to change.
EDIT 2:
$listing is ONE instance of the Listings model. So, you cannot call the empty() method on the object. I think you want to do something like this:
$listing = new Listings;
$listing->user_id = auth()->user()->id;
$listing->email= auth()->user()->email;
$listing->phone_number= auth()->user()->phone_number;
$listing->package = $request->session()->get('package');
$listing->save();
$listing->image1 = $fileNameToStore;
$listings = Listings::all();
return view('user.dashboard', compact('listings'));
Does this work out for you?
Ps. Do you want to set the image1 attribute AFTER you save it? This will get lost.
I think you are not importing model in the controller using namespace.
try to check using "Use auth" namespace
use App\Listing_Model;
use auth;
class DashboardController extends Controller {
public function index() {
$listing = new Listing_Model;
$listing->user_id = auth()->user()->id;
$listing->email= auth()->user()->email;
$listing->phone_number= auth()->user()->phone_number;
$listing->package = $request->session()->get('package');
$listing->save();
return view('user.dashboard');
}
}
When I click on the Signup button I receive the following error: Array to string conversion.
I think that the error occurs when I call fileInput() method but i don't know how to solve it.
This is the partial code of the view
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
While this is the code for the controller:
<?php
class SiteController extends Controller {
/**
* Signs user up.
*
* #return mixed
*/
public function actionSignup() {
$model = new SignupForm();
$modelUpload = new UploadForm();
if ($model->load(Yii::$app->request->post()) && $modelUpload->load(Yii::$app->request->post())) {
$modelUpload->imageFile = UploadedFile::getInstances($modelUpload, 'imageFile');
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user) && $modelUpload->upload()) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
'modelUpload' => $modelUpload,
]);
}
}
This is the code of the model. It's the same of the official documentation.
<?php
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;
}
}
}
?>
Errors:
Instant Solution
Change your line inside the actionSignup() from below
UploadedFile::getInstances($modelUpload, 'imageFile');
to
UploadedFile::getInstance($modelUpload, 'imageFile');
Reason
It's only a single file you are uploading not multiple files so getInstances() should be getInstance()
About
getInstance : Returns an uploaded file for the given model
attribute. The file should be uploaded using
[[\yii\widgets\ActiveField::fileInput()]]
getInstances: Returns all uploaded files for the given model
attribute.
if you want to upload multiple files - having'maxFiles' > 1 in your model's FileValidator rules - change your attribute name from:
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
to
<?= $form->field($modelUpload, 'imageFile[]')->fileInput() ?>
read this:
https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload#uploading-multiple-files
I am new to Yii. I am using this code
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'description')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'image')->fileInput(['type' => 'file']) ?>
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
When i try to print post data in my controller then image field is going blank;
If i print through $_FILES then file data is showing.
Please let me know how to get image in post method.
Step 1 :
In your model file define one variable.
public $uploadedImage;
Step 2 :
In your controller,
$model->uploadedImage = UploadedFile::getInstance($model, 'image');
$model->image = $model->uploadedImage->name;
After save() method write this to store image
$model->uploadedImage->saveAs('YOUR_WEBDIR_IMAGES_FOLDER/' . $model->uploadedImage->baseName . '.' . $model->uploadedImage->extension);
[If the above solution doesn't work then try this. :
Define another variable.
public $tempVarforImage;
In your controller
$model->tempVarforImage = $model->uploadedImage->name;
$model->image = $model->tempVarforImage;
(Because once I faced the issue in confliction of 'image' field from database and yii2 based 'image' variable)]
Create UploadForm model
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model{
public $image;// Image name
public function rules()
{
return [
[['image'], 'file'/* , 'skipOnEmpty' => false *//* , 'extensions' => 'png, jpg' */],
];
}
public function upload($fileName)
{
if ($this->validate()) {
$this->image->saveAs($fileName);
return true;
} else {
return false;
}
}
}
Controller code
Add at top of your file
use app\models\UploadForm;
use yii\web\UploadedFile;
Add this in your function
$model = User();
if ($model->load(Yii::$app->request->post())) {
$model1 = new UploadForm();
$model1->image = UploadedFile::getInstance($model, 'image');
$fileName = $model1->image->baseName.'_'.time();
$extension = $model1->image->extension;
$fileName = $fileName.'.'.$extension;
$filePath = WEBSITE_SLIDER_ROOT_PATH.$fileName;
if ($model1->upload($filePath)) {
//Save in database
}
}
i have an ActiveForm, and i want to add a field where the user can upload their photos.
the problem is that i don't have an attribute for the image in the users table and every
input field in 'yii' expects a model and an attribute as follows.
<?= $form->field($model, 'attribute')->input($platforms) ?>
i don't want to assign the image to any record nor i want to insert in in the database, i want it to be uploaded to a specific folder.
i have also checked the library kartik wrote, but also requires an attribute field.
Follow the official documentation
https://github.com/yiisoft/yii2/blob/master/docs/guide/input-file-upload.md
Form Model
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
/**
* UploadForm is the model behind the upload form.
*/
class UploadForm extends Model
{
/**
* #var UploadedFile|Null file attribute
*/
public $file;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['file'], 'file'],
];
}
}
?>
Form View
<?php
use yii\widgets\ActiveForm;
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'file')->fileInput() ?>
<button>Submit</button>
<?php ActiveForm::end(); ?>
Controller
Now create the controller that connects form and model together:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->file = UploadedFile::getInstance($model, 'file');
if ($model->validate()) {
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
}
}
return $this->render('upload', ['model' => $model]);
}
}
?>
Instead of model->load(...) we are using UploadedFile::getInstance(...). [[\yii\web\UploadedFile|UploadedFile]] does not run the model validation. It only provides information about the uploaded file. Therefore, you need to run validation manually via $model->validate(). This triggers the [[yii\validators\FileValidator|FileValidator]] that expects a file:
$file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE //in code framework
If validation is successful, then we're saving the file:
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
If you're using "basic" application template then folder uploads should be created under web.
That's it. Load the page and try uploading. Uplaods should end up in basic/web/uploads.
in your view
use kartik\widgets\ActiveForm;
use kartik\widgets\FileInput;
$form = ActiveForm::begin(['options' => ['enctype'=>'multipart/form-data']]); //important
echo FileInput::widget([
'name' => 'filename',
'showUpload' => false,
'buttonOptions' => ['label' => false],
'removeOptions' => ['label' => false],
'groupOptions' => ['class' => 'input-group-lg']
]);
echo Html::submitButton('Submit', ['class'=>'btn btn-primary']);
ActiveForm::end();
in your controller
$file = \yii\web\UploadedFile::getInstanceByName('filename');
$file->saveAs('/your/directory/'.$file->name);
Create a read only attribute for your model like public $imageand proceed like
<?= $form->field($model, 'image')->fileInput() ?>
I really like Yii2 Dropzone.
Installation:
composer require --prefer-dist perminder-klair/yii2-dropzone "dev-master"
Usage:
<?php
echo \kato\DropZone::widget([
'options' => [
'url'=> Url::to(['resource-manager/upload']),
'paramName'=>'image',
'maxFilesize' => '10',
],
'clientEvents' => [
'complete' => "function(file){console.log(file)}",
'removedfile' => "function(file){alert(file.name + ' is removed')}"
],
]);
?>
Controller:
public function actionUpload(){
$model = new ResourceManager();
$uploadPath = Yii::getAlias('#root') .'/uploads/';
if (isset($_FILES['image'])) {
$file = \yii\web\UploadedFile::getInstanceByName('image');
$original_name = $file->baseName;
$newFileName = \Yii::$app->security
->generateRandomString().'.'.$file->extension;
// you can write save code here before uploading.
if ($file->saveAs($uploadPath . '/' . $newFileName)) {
$model->image = $newFileName;
$model->original_name = $original_name;
if($model->save(false)){
echo \yii\helpers\Json::encode($file);
}
else{
echo \yii\helpers\Json::encode($model->getErrors());
}
}
}
else {
return $this->render('upload', [
'model' => $model,
]);
}
return false;
}
give this code after your uploaded code
//save the path in DB..
$model->file = 'uploads/'.$imageName.'.'.$model->file->extension;
$model->save();
If you have more than one file while uploading you must use foreach for that. And you should actual name of file in a column in table and a encrypted value of that name has to be stored to avoid duplicated in the directory.. Something like this..
$userdocs->document_name = UploadedFile::getInstances($userdocs, 'document_name');
foreach ($userdocs->document_name as $key => $file) {
$img_name = Yii::$app->security->generateRandomString();
$file->saveAs('user/business_files/' . $img_name . '.' . $file->extension);
$images = $img_name . '.' . $file->extension;
$userdocs->actual_name = $file->name;
$userdocs->user_id = $user->id;
$userdocs->document_name = $images;
$userdocs->save(false);
$userdocs = new UserDocs();
}
Here a random string is generated and it will be assign with the name of the document, and it will be stored in the table. The UserDocs is the model name.