So here it is.
I want to edit a data in database, it work perfectly if I upload an image every time I fill the form. but the problem raised when I edited another data and didn't upload an image instead of filling it with old image data (which is the file in my local) from database which is a string. the image validation makes the error was raised.
here my image validation
'image' => 'image|max:1024'
if I just put it like this 'image' => 'max:1024', it will run well because it wouldn't check if it's an image, but it will generate a problem where user start using edit data function to inject another unwanted code.
here is the update code
use WithFileUploads;
public $productId;
public $title;
public $description;
public $price;
public $image;
public $imageOld;
protected $listeners = [
'editProduct' => 'editProductHandler'
];
public function update()
{
$this->validate([
'title' => 'required|min:3',
'price' => 'required|numeric',
'description' => 'required|max:180',
'image' => 'image|max:1024'
]);
if ($this->productId) {
$product = Product::find($this->productId);
$image = '';
if ($this->image) {
Storage::disk('public')->delete($product->image);
$imageName = \Str::slug($this->title, '-')
. '-'
. uniqid()
. '.' . $this->image->getClientOriginalExtension();
$this->image->storeAs('public', $imageName, 'local');
$image = $imageName;
} else {
$image = $product->image;
}
$product->update([
'title' => $this->title,
'price' => $this->price,
'description' => $this->description,
'image' => $image
]);
$this->emit('productUpdated');
}
}
Related
can someone help me, i want to add article with image. image has successfully entered the directory but in the database the name is always D:\xampp\tmp\php......tmp.
I have changed the system file to public.
Controller
public function store(Request $request)
{
//
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
if ($request->file('thumbnail')) {
$imageName = time().'.'.$request->file('thumbnail')->getClientOriginalExtension();
$validatedData['thumbnail'] = $request->thumbnail->move(public_path('uploads/article/'), $imageName);
}
//dd($validateData['thumbnail']);
Article::create($validateData);
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
Try this
if ($request->file('thumbnail')) {
$imageName = time().'.'.$request->file('thumbnail')->getClientOriginalExtension();
$request->thumbnail->move(public_path('uploads/article/'), $imageName);
$validatedData['thumbnail'] = url('uploads/article/'.$imageName);
}
The reason why it's return a path instead of url because you're using public_path instead of url()
Controller Code
public function store(Request $request)
{
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
// Check if request has file
if($request->hasFile('thumbnail')){
// Get File
$file = $request->file('thumbnail');
// Get File Extention
$fileGetFileExtension = $file->getClientOriginalExtension();
// Create customized file name
$fileName = Str::random(20).'_'.date('d_m_Y_h_i_s').'.'.$fileGetFileExtension;
// Save File to your storage folder
Storage::disk('public')->put('uploads/article/'.$fileName,File::get($file));
}else{
$fileName = null;
}
$validatedData['thumbnail'] = $fileName;
Article::create($validateData);
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
Run php artisan storage:link, if not created
In blade you can get your file like this
I hope this helps. :D
thanks for your answer my problem has been solved with code like this, but only the name of the file stored in the database not with the name of the directory.
public function store(Request $request)
{
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
$imageName = time().'.'.$request->thumbnail->getClientOriginalExtension();
$request->thumbnail->move(public_path('articles/'), $imageName);
$Article = new Article;
$Article->title = $validateData['title'];
$Article->thumbnail = $imageName;
$Article->slug = $validateData['slug'];
$Article->description = $validateData['description'];
$Article->save();
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
I need upload a image to Google storage and insert the below JSON object with the gcs image path in MongoDB.
The image is successfully getting uploaded in GCS, but I am not able to get the image url of the image and also not able to update the path in mongoDB.
JSON object format
{
"original": "/pictures/1620305924456-74535-605b8a97a02cf2c1",
"thumbnail": "/pictures/1620305924456-74535-605b8a97a02cf2c1",
"fileType": "image"
}
Can anyone help me to implement the this logic.
public function store(Request $request)
{
request()->validate([
'name' => 'required',
'imageUrl' => 'required|image|mimes:jpeg,png,jpg|max:2048',
]);
$disk = Storage::disk('gcs');
$imagePath = $request->file('imageUrl');
$imageName = $imagePath->getClientOriginalName();
$disk->put('pictures', $request->file('imageUrl'));
$player->name ='test';
$player->imageUrl = [
'original' => '/pictures/nScT0KD7LoQucnfoFBLFfNAw9pmdfPnvtyC0VHq6.jpg',
'thumbnail' => '/pictures/nScT0KD7LoQucnfoFBLFfNAw9pmdfPnvtyC0VHq6.jpg',
'fileType'=> 'image'
];
Appreciation::create($player);
return redirect()->route('appreciation.index')
->with('success','Record created successfully.');
}
Thanks in advance
Finally I fixed it using below code .
request()->validate([
'name' => 'required',
'imageUrl' => 'required|image|mimes:jpeg,png,jpg|max:2048',
]);
$appreciation = new Appreciation();
$appreciation->name = $request->get('name');
$imagePath = $request->file('imageUrl');
$imageName = $imagePath->getClientOriginalName();
$disk = Storage::disk('gcs');
$url = $disk->url('/pictures/'.$imageName);
$disk->putFileAs('/pictures/', $request->file('imageUrl'), $imageName);
$data = [
'original' =>'/pictures/'.$imageName,
'thumbnail' => '/pictures/'.$imageName,
'fileType'=> 'image'
];
$appreciation->imageUrl = $data;
$appreciation->save();
Hey I'm having a hard time with this update method I have a slug field in my news model and it has to be unique, now when i update sometimes I may not want to change the slug but the validation of laravel doesnt let me send my data and when i bypass the validation Mysql won't let me insert into the slug field because of duplicate. this is my update method and validation I have a handleRequest wich is just to validate images being uploaded.
NewsController
public function update(CreateNewsRequest $request, $id)
{
$news = News::findOrFail($id);
$data = $this->handleRequest($request);
$news->update($data);
return redirect(route('admin.access.news.index'))->with('message', 'Your news has been updated');
}
CreateNewsRequest
public function authorize()
{
//if(access()->hasRole(1) || access()->hasRole(2))
return true;
}
public function rules(){
$news = $this->route()->parameter('news');
$rules = [
'title' => 'required',
'slug' => 'required|unique:news',
'excerpt' => 'required',
'body' => 'required',
'category_id' => 'required',
'image' => 'mimes:gif,bmp,jpeg,jpg,png',
];
switch($this->method()){
case 'PUT':
case 'PATCH':
$rules['slug'] = 'required|unique:news,slug,' .$news;
break;
}
return $rules;
}
}
I put this function in NewsController for now
private function handleRequest($request)
{
if(! $request->published_at ){
$request->published_at = null;
}
$data = $request->all();
if($request->hasFile('image'))
{
$image = $request->file('image');
$fileName = $image->getClientOriginalName();
$destination = public_path(config('cms.image.directory'));
$successUploaded = $image->move($destination, $fileName);
if($successUploaded)
{
$width = config('cms.image.thumbnail.width');
$height = config('cms.image.thumbnail.height');
$extension = $image->getClientOriginalExtension();
$thumbnail = str_replace(".{$extension}", "_thumb.{$extension}", $fileName);
Image::make($destination . '/' . $fileName)
->resize($width, $height)
->save($destination . '/' . $thumbnail);
}
$data['image'] = $fileName;
}
return $data;
}
You should ignore your current model by id not by other fields that can be changed in update form. Try this:
switch($this->method()){
case 'PUT':
case 'PATCH':
$id = $this->route('id');
$rules['slug'] = 'required|unique:news,slug,'.$id;
break;
}
#AndriyLozynskiy Editing works! Turns out I had a mistake in the form thanks for the help.
I also changed the validation a bit and created an UpdateFormRequest.php
public function rules(Request $request){
$news = $this->route('news');
$rules = [
'title' => 'required',
'excerpt' => 'required',
'body' => 'required',
'category_id' => 'required',
'image' => 'mimes:gif,bmp,jpeg,jpg,png',
'slug' => ($request->slug != $this->slug) ? 'required|alpha_dash|min:5|max:255|unique:news,slug' : ''
];
return $rules;
}
}
I have never sent images that were uploaded in a form to emails before, so I'm having a bit of trouble.
I know this line of code: $request->file('image')->move('/', $fileName); won't do anything because of where I'm moving it to, but that's as far as I could get reading these Laravel docs. As a matter of fact, it spits out this error:
Unable to write in the "/" directory
If I were to remove the above code and submit my form, everything works properly but the image fields shows up empty. That leads me to my question:
Where do I move the image to, and how do I get it from that location so that it can be used in the sent email rather than showing a blank spot as if nothing were uploaded?
Here are my files...
index.blade.php (image part of form only):
<div class="form-group">
{!! Form::file('image') !!}
</div>
emails/contact.blade.php (image part only):
<p>
Image: {{ $image }}
</p>
Requests/ContactFormRequest.php:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactFormRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required',
'height' => 'required',
'age' => 'required',
'weight' => 'required',
'gender' => 'required',
'email' => 'required|email',
'image' => 'required|mimes:jpeg,jpg,png|max:200px'
];
}
}
Auth/AboutController.php:
<?php namespace App\Http\Controllers;
use App\Http\Requests\ContactFormRequest;
class AboutController extends Controller {
public function create()
{
return view('pages.index');
}
public function store(ContactFormRequest $request)
{
$fileName = "Image";
$request->file('image')->move('/', $fileName);
\Mail::send('emails.contact',
array(
'name' => $request->get('name'),
'height' => $request->get('height'),
'age' => $request->get('age'),
'weight' => $request->get('weight'),
'gender' => $request->get('gender'),
'email' => $request->get('email'),
'image' => $request->get('image')
), function($message)
{
$message->from('example#example.com');
$message->to('example#example.com', 'Admin')->subject('Example Text');
});
return \Redirect::route('/')
->with('message', 'Your application is on its way!');
}
}
if you want to attach a picture to a mail use this:
Mail::send('emails.contact',
array(
'name' => $request->get('name'),
'height' => $request->get('height'),
'age' => $request->get('age'),
'weight' => $request->get('weight'),
'gender' => $request->get('gender'),
'email' => $request->get('email'),
'image' => $filename
), function($message) use($filename)
{
$message->from('example#example.com');
$message->to('example#example.com', 'Admin')->subject('Example Text');
$message->attach('/'.$filename);
});
usually i did this for uploading picture.
//Request File
$file = $request->file('image');
//Destination
$destination = public_path() . '/img/';
//Define the name
$name= "image";
//Get file extension
$extension = $file->getClientOriginalExtension();
//join the name you set with the extension
$filename = $name . '.' . $extension;
//after that move the file to the directory
$file->move($destination, $filename);
If you want to show the image don't forget use (instead of returning its name)
<img src="foo/bar" />
I have followed different implementation of file/image upload in Yii 2. One of which is from Kartik's widgets, which is in here: http://demos.krajee.com/widget-details/fileinput
In my view, _form.php:
<div class="col-sm-8">
<?php
// A block file picker button with custom icon and label
echo FileInput::widget([
'model' => $model,
'attribute' => 'image',
'options' => ['multiple' => true],
'pluginOptions' => [
'showCaption' => false,
'showRemove' => false,
'showUpload' => false,
'browseClass' => 'btn btn-primary btn-block',
'browseIcon' => '<i class="glyphicon glyphicon-camera"></i> ',
'browseLabel' => 'Upload Receipt'
],
'options' => ['accept' => 'image/*']
]);
?>
</div>
I only showed you a part of my view. That image upload block is accompanied with other fields like Customer Name, Date From and To, Product Name, etc and a Submit button.
I also have models and controllers generated already.
Part of my controller is this:
public function actionCreate()
{
$model = new Invoice();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->inv_id]);
}
else {
return $this->render('create', [
'model' => $model,
]);
}
}
I have not added anything yet in my actionCreate because I still don't have any idea. And in Kartik's file upload demo, there are no controllers involved or shown.
How do I save the URL/path of the image I chose to upload in my database, and save that image locally?
Edit:
Regarding #arogachev's answer, here's what my afterSave looks like in my model, but still the image path is not saved in my db:
public function afterSave($insert, $changedAttributes)
{
if(isset($this->image)){
$this->image = UploadedFile::getInstance($this,'image');
if(is_object($this->image)){
$name = Yii::$app->basePath . 'C:\wamp3\www\basicaccounting\web\uploads'; //set directory path to save image
$this->image->saveAs($name.$this->inv_id."_".$this->image);
$this->image = $this->inv_id."_".$this->image; //appending id to image name
Yii::$app->db->createCommand()
->update('invoice', ['image' => $this->image], 'inv_id = "'.$this->inv_id.'"')
->execute(); //manually update image name to db
}
}
}
Use the below aftersave in your model
public function afterSave($insert, $changedAttributes)
{
if(isset($this->logo)){
$this->logo=UploadedFile::getInstance($this,'logo');
if(is_object($this->logo)){
$path=Yii::$app->basePath . '/images/'; //set directory path to save image
$this->logo->saveAs($path.$this->id."_".$this->logo); //saving img in folder
$this->logo = $this->id."_".$this->logo; //appending id to image name
\Yii::$app->db->createCommand()
->update('organization', ['logo' => $this->logo], 'id = "'.$this->id.'"')
->execute(); //manually update image name to db
}
}
}
replace the above logo with your own attribute. ie. image
Try given below -
In your Controller
if($model->image = UploadedFile::getInstance($model, 'image'))
{
if ($model->upload())
{
// file is uploaded successfully
}
}
In your Model
public function upload()
{
$path = \Yii::$app->params['basepath'];
if (!is_dir($path)) {
$image_path = BaseFileHelper::createDirectory($path,0777,true);
}
$this->image->saveAs($path . date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension);
$this->image = date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension; // Assign image path to store in Database column (image).
return true;
}
Your image will be save on server as "$path . date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension".
and in the database it will be save as "date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension".
In form
<?= $form->field($model, 'images[]')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*', 'multiple' => true],
'pluginOptions' => [
'previewFileType' => 'image',
'allowedFileExtensions' => ['jpg', 'gif', 'png', 'bmp','jpeg'],
'showUpload' => true,
'overwriteInitial' => true,
],
]);
?>
In Model
public $images;
public function rules()
{
return [
[['name', 'price'], 'required'],
[['price'], 'integer'],
[['images'],'file', 'maxFiles' => 4],
[['name'], 'string', 'max' => 100],
];
}
In Controller
public function actionCreate()
{
$model = new Product();
if ($model->load(Yii::$app->request->post())) {
$model->save();
$file = UploadedFile::getInstances($model, 'images');
foreach ($file as $file) {
$path =Yii::getAlias('#frontend').'/uploads/'.$file->name;
$file->saveAs($path);
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}