Delete images of different folders in laravel - php

I've saved images of posts in different sub-folders inside public/images like featured_image (public/images/featured_image), banner(public/images/banner). I want to delete images(featured_image and banner) related to post when banner is deleted.
This is my setup in filesystem.php
'local' => [
'driver' => 'local',
'root' => public_path('images/'),
],
I'm trying this to delete posts and images related to this:
public function destroy($id)
{
//
$tour = Tour::find($id);
$tour->country()->detach();
Storage::delete('featured_image/$tour->featured_image');
Storage::delete('banner/$tour->banner');
$tour->delete();
Session::flash('success', 'The tour is sucessfully deleted.');
return redirect()->route('tours.index');
}
The post gets deleted successfully but the images are not deleted from the folder. Please suggest the possible solution.

It should be
Storage::delete('images/featured_image/' . $tour->featured_image);
Storage::delete('images/banner/' . $tour->banner);
If that doesn't work... you can also do.
$images = [
'featured_image' => public_path('images/featured_image/' . $tour->featured_image),
'banner_image' => public_path('images/banner/' . $tour->banner),
];
foreach($images as $image) {
if(file_exists($image)) {
unlink($image);
}
}

I got this working by using File:delete(); method.
public function destroy($id)
{
$tour = Tour::find($id);
$tour->country()->detach();
File::delete(public_path('/images/featured_image/' . $tour->featured_image));
File::delete(public_path('/images/banner/' . $tour->banner));
$tour->delete();
Session::flash('success', 'The tour is sucessfully deleted.');
return redirect()->route('tours.index');
}

Related

Laravel sync makes a duplicate date in pivot table if multiple images selected

Why does sync makes duplicate sync in the pivot table if i selects more than an image ?
In my application when adding a new competition a user can select one or more images/documents and the file path will be saved in the files table and sync the data into the competition_file pivot table.
Here's the create UI
Here's the store function on my controller
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, ['competition_id' => $competition,'team_id' => $request->team,'type' => $request->type,'share_type' => $request->share_type]);
$team->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))->with('success', 'Document updated.');
}
Here's the relationship codes in my model
public function documents()
{
return $this->belongsToMany(File::class,'competition_file','team_id','file_id')->wherePivot('type', 'document');
}
When i selectes more than one image as below it makes a duplicate in the competition_file table
This is how it saves in the competition_file pivot table with a duplicate data
But if Dump the data before sync while I have selected two images it shows only two array see below codes
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, ['competition_id' => $competition,'team_id' => $request->team,'type' => $request->type,'share_type' => $request->share_type]);
dd($forSync);
$team->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))->with('success', 'Document updated.');
}
Result
And if I remove the Dump and reloads the same page it syncs correctly
And if I retry without Dump and if I selects two image and save it creates a duplicate ?
I need to know what might be creating the duplicate sync.
I hope my question is clear, can someone please help me out.
Just for the benefit of subsequent visitors.
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, [
'competition_id' => $competition,
'type' => $request->type,
'share_type' => $request->share_type
]);
//If the implicit route model binding is not working
//if $team is null or you need to explicitly set the team
//selected by user and which is not passed as route param
Team::findOrFail($request->team)->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))
->with('success', 'Document updated.');
}

I can't see my update profile image using laravel 6

i am trying to update the image of profil ,because to user at the beginning it creates account without image, after it goes the update, so i store the image in root /aswakfolder/public/storage/profiles and i insert image link in db profiles/nameimage.jpeg, i created a function in helpers.php file to display the image its work very will, the problem here is that I do not understand the helpers function, and it does not meet my needs, my need is when image upload and exists it displays my image if not it displays image not-found.jpeg,in my case it always displays not-found.jpeg.
stock image in my folder, and url image insert in db very well.
UsersController.php
public function update(Request $request, $id)
{
$user=User::find($id);
if($request->hasFile('image'))
{
$image = $request->file('image');
$path = $request->image->store('profiles');
$user->image = $path;
}
$request->image = $user->image;
$user->id = Auth::user()->id;
$user->update([
$user->name => $request->name,
$user->email => $request->email,
$user->telephone => $request->telephone,
$user->daten => $request->daten,
$user->country_id=> $request->country_id,
$user->state_id => $request->state_id,
$user->city_id => $request->city_id,
$user->image => $request->image,
]);
session()->flash('success', 'user updated successfully !!');
return redirect('users');
}
helpers.php
function productImage($path)
{
return $path && file_exists('/aswakfolder/public/storage/'.$path) ? asset('/aswakfolder/public/storage/'.$path) : asset('/aswakfolder/public/storage/not-found.jpg');
}
index.blade.php
<div class="inner" style="background-image: url({{ asset(productImage($users->image)) }})">
Make sure you run the commend php artisan storage:link to create the shortcurt on public/ folder.
Documentation

how to delete multiple records that involve images in laravel

Please guys any idea how to delete multiple records that involve images. i do not know any approach that i can use. i have tried a lot.this is the what i have tried below.Pls help me guys i really need your help.Thanks in advance
please this is the code below
public function multipleUserDelete(Request $request,$id, $post_image){
if ($request->isMethod("post")) {
$data=$request->all();
//$del_user = $request->del_user;
// $ids=$del_user[];
//foreach(session('posts') as $session){
//foreach(session('products') as $postDelete){
$postDeletes=Post::where(['id'=> $id])
->where('post_image', $post_image)
->get();
foreach ($postDeletes as $postDelete) {
# code...
// $postDeletes=Post::where(['id'=> $id])->get();
//}
$large_image_paths='images/backend_image/admin_users/small/';
$medium_image_paths='images/backend_image/admin_users/medium/';
$small_image_paths='images/backend_image/admin_users/large/';
//Delete Image permenently from product table begins
//Delete Large image if not exist
if(file_exists($large_image_paths. $postDelete->post_image)){
unlink($large_image_paths. $postDelete->post_image);
}
//Delete Large image if not exist
if(file_exists($small_image_paths. $postDelete->post_image)){
unlink($small_image_paths. $postDelete->post_image);
}
//Delete Medium image if not exist
if(file_exists($medium_image_paths. $postDelete->post_image)){
unlink($medium_image_paths. $postDelete->post_image);
}
}
//$del_id=$request->input('del_feedback');
Post::whereIn('id', $data['del_user'])->delete();
return redirect()->back()->with("flash_message_success","you Successfully Deleted The Selected Users(s)");
}
Not tested, but I think something like this should work fine.
$image_path = "/images/"; // Value is not URL but directory file path
Post::where(['id'=> $id])
->where(function($query){
if(File::exists($image_path . $post_image)) {
File::delete($image_path . $post_image);
}
$query->where('post_image', $post_image)
})
->delete();
In general, the path issue should probably be
absolute.
See How to delete file from public folder in laravel 5.1
I don't know in Laravel 6, but it should work.
i.e. using File :: delete ()
Add the folder that contains your image to your config/filesystems.php files:
'disks' => [
'local' => [
'driver' => 'local',
'root' => base_path('app'),
],
//Above bit should already be there. So add this....
'some-image-path' => [
'driver' => 'local',
'root' => base_path("wherever/your/directory/is/from/root/"),
],
You would then use it like this:
$myImage = 'some-image.png';
Storage::disk('some-image-path')->delete($myImage);
public function multipleUserDelete(Request $request,$id, $post_image){
if ($request->isMethod("post")) {
$data=$request->all();
$postDeletes=Post::where(['id'=> $id])
->where('post_image', $post_image)
->get();
$img_array = array();
foreach ($postDeletes as $postDelete) {
$large_image_paths='images/backend_image/admin_users/small/';
$medium_image_paths='images/backend_image/admin_users/medium/';
$small_image_paths='images/backend_image/admin_users/large/';
$img='';
if(file_exists(public_path($large_image_paths. $postDelete->post_image))){
$img = $large_image_paths. $postDelete->post_image;
}
if(file_exists(public_path($small_image_paths. $postDelete->post_image))){
$img = $small_image_paths. $postDelete->post_image;
}
if(file_exists(public_path($medium_image_paths. $postDelete->post_image))){
$img = $medium_image_paths. $postDelete->post_image;
}
array_push($img_array,$img);
}
\File::delete($img_array);
Post::whereIn('id', $data['del_user'])->delete();
return redirect()->back()->with("flash_message_success","you Successfully Deleted The Selected Users(s)");
}

yii2 - Kartik file input - update

This is the situation: I'm new on Yii2 and wanted to use some file uploader widget within ActiveForm.. so far I've found this excelent one: \kartik\widget\FileInput
With this widget I can manage file upload and then, when enter in edit mode, show the previous uploaded image with the oportunite to replace it.
The problem is that if I press the "Update" button of the form without modifying the image yii says that the image "can't be empty" because I've set the 'required' rule in my model.
After an awful afternoon and a more productive night, I've encountered a solution that worked for me..
The main problem was that file input don't send its value (name of the file stored in database) when updating. It only sends the image info if browsed and selected through file input..
So, my workaround was creating another "virtual" field for managing file upload, named "upload_image". To achieve this I simple added a public property with this name to my model class: public $upload_image;
I also add the folowing validation to rules method on Model class:
public function rules()
{
return [
[['upload_image'], 'file', 'extensions' => 'png, jpg', 'skipOnEmpty' => true],
[['image'], 'required'],
];
}
Here, 'upload_image' is my virtual column. I added 'file' validation with 'skipOnEmpty' = true, and 'image' is the field on my database, that must be required in my case.
Then, in my view I configured 'upload_image' widget like follows:
echo FileInput::widget([
'model' => $model,
'attribute' => 'upload_image',
'pluginOptions' => [
'initialPreview'=>[
Html::img("/uploads/" . $model->image)
],
'overwriteInitial'=>true
]
]);
In 'initialPreview' option I asign my image name, stored in '$model->image' property returned from database.
Finally, my controller looks like follow:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->load(Yii::$app->request->post());
if(Yii::$app->request->isPost){
//Try to get file info
$upload_image = \yii\web\UploadedFile::getInstance($model, 'upload_image');
//If received, then I get the file name and asign it to $model->image in order to store it in db
if(!empty($upload_image)){
$image_name = $upload_image->name;
$model->image = $image_name;
}
//I proceed to validate model. Notice that will validate that 'image' is required and also 'image_upload' as file, but this last is optional
if ($model->validate() && $model->save()) {
//If all went OK, then I proceed to save the image in filesystem
if(!empty($upload_image)){
$upload_image->saveAs('uploads/' . $image_name);
}
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
]);
}
I have encountered another solution by creating scenarios. In your case I would modify the rules like this:
public funtion rules() {
[['image'], 'file'],
[['image'], 'required', 'on'=> 'create']
}
So the fileupload field will be required only in create action. In update action I have this code:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$newCover = UploadedFile::getInstance($model, 'image');
if (!empty($newCover)) {
$newCoverName = Yii::$app->security->generateRandomString();
unlink($model->cover);
$model->cover = 'uploads/covers/' . $newCoverName . '.' . $newCover->extension;
$newCover->saveAs('uploads/covers/' . $newCoverName . '.' . $newCover->extension);
}
if ($model->validate() && $model->save()) {
return $this->redirect(['view', 'id' => $model->post_id]);
} else {
// error saving model
}
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
In the update scenario the image filed is not required but the code checks if nothing was uploaded and doesn't change the previous value.
My form file:
<?= $form->field($model, 'image')->widget(FileInput::classname(), [
'options' => ['accept'=>'image/*'],
'pluginOptions'=>[
'allowedFileExtensions'=>['jpg', 'gif', 'png', 'bmp'],
'showUpload' => true,
'initialPreview' => [
$model->cover ? Html::img($model->cover) : null, // checks the models to display the preview
],
'overwriteInitial' => false,
],
]); ?>
I think is a little more easier than a virtual field. Hope it helps!
Try preloading the file input field with the contents of that field. This way, you will not lose data after submitting your form.
I looked through kartik file-input widget (nice find, btw) and I came across a way to do this
// Display an initial preview of files with caption
// (useful in UPDATE scenarios). Set overwrite `initialPreview`
// to `false` to append uploaded images to the initial preview.
echo FileInput::widget([
'name' => 'attachment_49[]',
'options' => [
'multiple' => true
],
'pluginOptions' => [
'initialPreview' => [
Html::img("/images/moon.jpg", ['class'=>'file-preview-image', 'alt'=>'The Moon', 'title'=>'The Moon']),
Html::img("/images/earth.jpg", ['class'=>'file-preview-image', 'alt'=>'The Earth', 'title'=>'The Earth']),
],
'initialCaption'=>"The Moon and the Earth",
'overwriteInitial'=>false
]
]);
You may also want to relax the required rule in your model for that field, so it does not complain on validation. You may choose to prompt the user through subtler means.
From Krajee:
http://webtips.krajee.com/advanced-upload-using-yii2-fileinput-widget
Create, delete, update: really easy, look no further.
(1) I've set the 'required' rule in my model too.
(2) To work on Wampserver:
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/';
Yii::$app->params['uploadUrl'] = Yii::$app->urlManager->baseUrl . '/uploads/';

PHP Laravel Framework Uploading Image Form Processing

I'm trying to learn to an process image form that uploads images to a database and lets users view the image on the website, this is done using Laravel 4. I must have some sort of bug, because the view doesn't have any errors, but when I select an image to upload and hit the "save" button on my form, nothing happens other than it looks like the form has been refreshed because the file is gone.
Routes
// This is for the get event of the index page
Route::get('/', array(
'as' => 'index_page',
'uses' => 'ImageController#getIndex'
));
// This is for the post event of the index page
Route::post('/', array(
'as' => 'index_page_post',
'before' => 'csrf',
'uses' => 'ImageController#postIndex'
));
ImageController.php
class ImageController extends BaseController {
public function getIndex()
{
// Let's first load the form view
return View::make('tpl.index');
}
public function postIndex()
{
// Let's validate the form first with the rules which are set at the model
$input = Input::all();
$rules = Photo::$upload_rules;
$validation = Validator::make($input, $rules);
// If the validation fails, we redirect the user to the index page, with errors
if ($validation->passes()) {
// If the validation passes, we upload the image to the database and process it
$image = Input::file('image');
// This is the original uploaded client name of the image
$filename = $image->getClientOriginalName();
// Because Symfony API does not provide filename
// without extension, we will be using raw PHP here
$filename = pathinfo($filename, PATHINFO_FILENAME);
// We should salt and make an url-friendly version of the file
$fullname = Str::slug(Str::random(8) . $filename) . '.' .
$image->getClientOriginalExtension();
// We upload the image first to the upload folder, then
// get make a thumbnail from the uploaded image
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
// If the file is now uploaded we show a success message
// otherwise, we show an error
if ($upload) {
// image is now uploaded, we first need to add column to the database
$insert_id = DB::table('photos')->insertGetId(
array(
'title' => Input::get('title'),
'image' => $fullname
)
);
// Now we redirect to the image's permalink
return Redirect::to(URL::to('snatch/'.$insert_id))
->with('success', 'Your image is uploaded successfully!');
}
else {
// Image cannot be uploaded
return Redirect::to('/')->withInput()
->with('error', 'Sorry, the image could not be uploaded.');
}
}
else {
return Redirect::to('/')
->withInput()
->withErrors($validation);
}
}
Image Model
class Photo extends Eloquent {
// the variable that sets the table name
protected $table = 'photos';
// the variable that sets the table name
protected $fillable = array('title', 'image');
// the timestamps enabled
public $timestamps = true;
// Rules of the image upload form
public static $upload_rules = array(
'title' => 'required|min:3',
'image' => 'required|image'
);
}
The view for the form
#extends('frontend_master')
#section('content')
{{ Form::open(array('url' => '/', 'files' => true )) }}
{{ Form::text('title', '', array(
'placeholder' => 'Please insert your title here')) }}
{{ Form::file('image') }}
{{ Form::submit('save', array('name' => 'send')) }}
{{ Form::close() }}
#stop
Let me know if you can find any bugs, I'm pretty sure something must be going wrong in my ImageController#postIndex
Thanks for any insights
2 things you need to check out.
1st off, once you updated your composer.json to include the Intervention/Image package. you should run composer dump-autoload to refresh the autoload file.
2ndly, there's a logical error in your controller.
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
should be
Image::make(Config::get('image.image_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
because you've already moved the image file to image_folder with the code below:
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Hope this helps.

Categories