Laravel unlink method - laravel

can someone tell me how to unlink image from public path when product is deleted.
My current code which does not work:
public function destroy($id)
{
$product = Product::findOrFail($id);
$image_path = '/uploads/products/' . $product->image;
if(file_exists($image_path)){
unlink($image_path);
}
$product->delete();
}
Also tried:
$product = Product::findOrFail($id);
if(file_exists($product->image)){
unlink($product->image);
}
$product->delete();
Also I am using accessor so my $product->image is returning:
"http://myeshop.local/uploads/products/1593902362bluesocksupd.jpg"
Here is accessor code:
public function getImageAttribute($image){
return asset($image);
}

use model deleted event
//Product Model
protected static function boot()
{
parent::boot();
static::deleted(function($product){
// getOriginal skip accessor
$image = public_path('uploads/products/' . $product->getOriginal('image'));
if(file_exists($image)) {
unlink($image);
}
});
}

unlink($path) is a PHP function. It will delete a file located at a local path. According to your question the value of $product->image is the complete URL to the image. If it is then the following is true:
$product = Product::findOrFail($id);
$image_path = '/uploads/products/' . $product->image;
// $image_path = '/uploads/products/http://myeshop.local/uploads/products/1593902362bluesocksupd.jpg'
// and it needs to point to '/PATH/TO/LARAVEL/uploads/products/1593902362bluesocksupd.jpg'
// the following file_exists() will return false
if(file_exists($image_path)){
unlink($image_path); // so you never get here
}
There are some quick and dirty ways to fix this, but the best thing to do is to have the $product->image property point to just the name of the file. Then in your view apply the file name to the /uploads/products/ directory on the web server.
Doing this will allow you to apply the /uploads/products/ local path and have a better time finding the file you want to delete. I'm assuming the uploads directory is in your Laravel public directory so you'd want to do something like this:
// $product->image must point to the filename only: 1593902362bluesocksupd.jpg
// The file_exists should evaluate to true and unlink() will work.
$image_path = public_path('uploads/products/' . $product->image);
if(file_exists($image_path)){
unlink($image_path);
}
In your Blade template view you'd need to show the product image using something like this:
<img src="{{ url('/uploads/products/' . $product->image) }}" />
Storing a complete URL in your database doesn't scale well if you wanted to develop another website or reuse this code on another project. This way you can let Laravel manage where the URL or local file system is.

You could use PHP's unlink() method.
But if you want to do it the Laravel way, use the Storage::delete method instead :
use Illuminate\Support\Facades\Storage;
public function destroy($id)
{
$product = Product::findOrFail($id);
$image_path = public_path('uploads/products/' . $product->image);
if(file_exists($image_path)){
Storage::delete($image_path);
}
$product->delete();
}

Related

Laravel unlink doesn't delete the file [duplicate]

I want to delete a News from database and when I hit the delete button all data from database deleted but the image is remains in upload folder.
So, how do I this to work.
thanks
This is my function again but does not delete the image from images/news folder of public directory>
public function destroy($id) {
$news = News::findOrFail($id);
$image_path = app_path("images/news/{$news->photo}");
if (File::exists($image_path)) {
//File::delete($image_path);
unlink($image_path);
}
$news->delete();
return redirect('admin/dashboard')->with('message','خبر موفقانه حذف شد');
}
You could use PHP's unlink() method just as #Khan suggested.
But if you want to do it the Laravel way, use the File::delete() method instead.
// Delete a single file
File::delete($filename);
// Delete multiple files
File::delete($file1, $file2, $file3);
// Delete an array of files
$files = array($file1, $file2);
File::delete($files);
And don't forget to add at the top:
use Illuminate\Support\Facades\File;
Use the unlink function of php, just pass exact path to your file to unlink function :
unlink($file_path);
Do not forget to create complete path of your file if it is not stored in the DB. e.g
$file_path = app_path().'/images/news/'.$news->photo;
this method worked for me
First, put the line below at the beginning of your controller:
use File;
below namespace in your php file
Second:
$destinationPath = 'your_path';
File::delete($destinationPath.'/your_file');
$destinationPath --> the folder inside folder public.
This worked at laravel 8
use File;
if (File::exists(public_path('uploads/csv/img.png'))) {
File::delete(public_path('uploads/csv/img.png'));
}
First, you should go to config/filesystems.php and set 'root' => public_path() like so:
'disks' => [
'local' => [
'driver' => 'local',
'root' => public_path(),
],
Then, you can use Storage::delete($filename);
Update working for Laravel 8.x:
Deleting an image for example ->
First of all add the File Facade at the top of the controller:
use Illuminate\Support\Facades\File;
Then use delete function. If the file is in 'public/' you have to specify the path using public_path() function:
File::delete(public_path("images/filename.png"));
Using PHP unlink() function, will have the file deleted
$path = public_path()."/uploads/".$from_db->image_name;
unlink($path);
The above will delete an image returned by $from_db->image_name located at public/uploads folder
Try to use:
unlink('.'.Storage::url($news->photo));
Look the dot and concatenation before the call of facade Storage.
public function destroy($id) {
$news = News::findOrFail($id);
$image_path = app_path("images/news/".$news->photo);
if(file_exists($image_path)){
//File::delete($image_path);
File::delete( $image_path);
}
$news->delete();
return redirect('admin/dashboard')->with('message','خبر موفقانه حذف شد');
}
First make sure the file exist by building the path
if($request->hasFile('image')){
$path = storage_path().'/app/public/YOUR_FOLDER/'.$db->image;
if(File::exists($path)){
unlink($path);
}
Try it :Laravel 5.5
public function destroy($id){
$data = User::FindOrFail($id);
if(file_exists('backend_assets/uploads/userPhoto/'.$data->photo) AND !empty($data->photo)){
unlink('backend_assets/uploads/userPhoto/'.$data->photo);
}
try{
$data->delete();
$bug = 0;
}
catch(\Exception $e){
$bug = $e->errorInfo[1];
}
if($bug==0){
echo "success";
}else{
echo 'error';
}
}
the easiest way for you to delete the image of the news is using the model event like below
and the model delete the image if the news deleted
at first you should import this in top of the model class use Illuminate\Support\Facades\Storage
after that in the model class News you should do this
public static function boot(){
parent::boot();
static::deleting(function ($news) {
Storage::disk('public')->delete("{$news->image}");
})
}
or you can delete the image in your controller with
this command
Storage::disk('public')->delete("images/news/{$news->file_name}");
but you should know that the default disk is public but if you create folder in the public folder and put the image on that you should set the folder name before $news->file_name
This is the way I upload the file and save it into database and public folder and also the method I delete file from database and public folder.
this may help you and student to get complete source code to get the task done.
uploading file
at the first if you save file into database by giving path public_path() once it not need to used in delete method again
public function store_file(Request $request)
{
if($request->hasFile('file'))
{
$fileExtention = $request->file('file')->getClientOriginalExtension();
$name = time().rand(999,9999).$request->filename.'.'.$fileExtention;
$filePath = $request->file('file')->move(public_path().'/videos',$name);
$video = new Video_Model;
$video->file_path = $filePath;
$video->filename = $request->filename;
$video->save();
}
return redirect()->back();
}
deleting file
from database and public folder as you saved
public function delete_file(Request $request)
{
$file = Video_Model::find($request->id);
$file_path = $file->file_path;
if(file_exists($file_path))
{
unlink($file_path);
Video_Model::destroy($request->id);
}
return redirect()->back();
}
Its a very old thread, but I don't see that the solution is here or the this thread is marked as solved. I have also stuck into the same problem I solved it like this
$path = public_path('../storage/YOUR_FOLDER_NAME/YOUR_FILE_NAME');
if (!File::exists($path))
{
File::delete(public_path('storage/YOUR_FOLDER_NAME/YOUR_FILE_NAME'));
}
The key is that you need to remove '..' from the delete method. Keep in mind that this goes true if you are using Storage as well, whether you are using Storage of File don't for get to use them like
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use File; // For File
use Storage; // For Storage
Hope that it will help someone.
For Delete files from the public folders, we can use the File::delete function into the Laravel. For use File need to use File into the controller OR We can use \File. This consider the root of the file.
// Delete a single file
File::delete($filename);
For delete Multiple files
// Delete multiple files
File::delete($file1, $file2, $file3);
Delete an array of Files
// Delete an array of files
$files = array($file1, $file2);
File::delete($files);
Two ways to delete the image from public folder without changing laravel filesystems config file or messing with pure php unlink function:
Using the default local storage you need to specify public subfolder:
Storage::delete('public/'.$image_path);
Use public storage directly:
Storage::disk('public')->delete($image_path);
I would suggest second way as the best one.
Hope this help other people.
If you store your image in folder public, try this steps:
For example your image is sample.jpg and your path is public/img/sample.jpg
so this codes will delete your image
use Illuminate\Support\Facades\File;
.
.
.
public function deleteImage(){
$imgWillDelete = public_path() . '/img/sample.jpg';
File::delete($imgWillDelete);
}
Follow the steps carefully to get the image first=>
$img = DB::table('students')->where('id',$id)->first();
$image_path = $img->photo;
unlink($image_path);
DB::table('students')->where('id',$id)->delete();
For delete file from folder you can use unlink and if you want to delete data from database you can use delete() in laravel
Delete file from folder
unlink($image_path);
For delete record from database
$flight = Flight::find(1);
$flight->delete();
public function update(Request $request, $id)
{
$article = Article::find($id);
if($request->hasFile('image')) {
$oldImage = public_path($article->image);
File::delete($oldImage);
$fileName = time().'.'.$request->image->extension();
$request->image->move(public_path('uploads/'), $fileName);
$image ='uploads/'.$fileName;
$article->update([
'image' => $image,
]);
}
$article->update([
'title' => $request->title,
'description' => $request->description,
]);
return redirect()->route('admin.article.index');
}
you can delete file and its record like wise:
public function destroy($id)
{
$items = Reports::find($id); //Reports is my model
$file_path = public_path('pdf_uploads').'/'.$items->file; // if your file is in some folder in public directory.
// $file_path = public_path().'/'.$items->file; use incase you didn't store your files in any folder inside public folder.
if(File::exists($file_path)){
File::delete($file_path); //for deleting only file try this
$items->delete(); //for deleting record and file try both
}
return redirect()->back()->with('message','client code: '.$items->receipt_no.' report details has been successfully deleted along with files');
}
note: items->file is my attribute in database where I have stored the name of the file like so,
I have stored the file in the directory "public/pdf_uploads/filename"
Don't forget to add this in your header
use Illuminate\Support\Facades\File;
For File Syntax:
if(File::exists(public_path('upload/test.png'))){
File::delete(public_path('upload/test.png'));
}else{
dd('File does not exists.');
}
For Storage Syntax:
if(Storage::exists('upload/test.png')){
Storage::delete('upload/test.png');
/*
Delete Multiple File like this way
Storage::delete(['upload/test.png', 'upload/test2.png']);
*/
}else{
dd('File does not exists.');
}
Common Method is :
#unlink('/public/admin/pro-services/'.$task->pro_service_image);

Write function in controller below controller class?

Is that a good practice to wrap some code from controller class method because it's too long and put that code in another custom function below controller class.
Here is controller method:
public function store(UploadRequest $request)
{
//Provjera duljine imena slike (max 20 znakova)
if(!is_valid_name($request->file('file'))) {
return redirect()->back()->withErrors(['File name can\'t be longer than 20 characters.']);
}
$user = Auth::user();
$time = time();
$image = $request->file('file');
//Dodaj trenutno vrijeme prije imena slike kako bi se slika mogla identificirati
$image_name = $time . $image->getClientOriginalName();
//Ako je slika png spremi ju bez konverzije
if($image->getClientOriginalExtension() == "png")
{
Storage::put('public/images/'.$user->id.'/png/'.$image_name, file_get_contents($image));
save_image_to_database($image, $user, $time);
}
Save_image_to_database() is my custom function that is written below controller class:
function save_image_to_database($image, $user, $time){
$db_image = new Image();
if($image->extension() == 'png')
{
$db_image->path = $time . $image->getClientOriginalName();
$db_image->png_size = $image->getClientOriginalSize();
}
else
{
$path = $time . pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME).'.png';
$png_size = Storage::size('/public/images/'.$user->id.'/png/'.$path);
$db_image->path = $path;
$db_image->png_size = $png_size;
}
$db_image->user_id = $user->id;
$db_image->extension = $image->extension();
$db_image->size = $image->getClientSize();
$db_image->save();
return redirect('/images');
}
Problem is that redirect() method in custom function is not working, it redirects to blank window but the path in browser "localhost:8000/images" is correct.When I manually refresh the site then it works and the view is returned. If I move that redirect() method from custom function to controller store() then it works well.
Your function returns Response object but controller doesn't use it
The most simple solution for you will be to return the response of helper function like
return save_image_to_database($image, $user, $time);
However I would at least wrap it in try-catch to handle inability to save file like
try {
save_image_to_database($image, $user, $time);
} catch (\Exception $e) {
// return error response
}
// if we got here image was successfully saved
return redirect('/images');
Now back to your question about if its a good experience to handle image as another controller method.. I'd say no, you want to keep your controllers very skinny and have only methods that are used by Router
I'd either move it into a Trait (Traits in PHP) and use that trait in the controller or make an Image Service and use it via dependency injection.

Laravel 5.3: delete image from storage

I have a method which deletes a product and image that belongs to it, but I can not delete the image.
Where am I going wrong with this?
public function deleteProduct($ids)
{
foreach ($ids as $id => $value) {
$product = Product::find($id);
$productImage = $product->image_path;
if ($productImage) {
Storage::delete($productImage);
$product->destroy($id);
}
}
}
I have a symlink between storage and public folder.
Under storage images are located at e.g. - storage/app/public/images/products/4/image.png
Under public - public/storage/images/products/4/imagep.png
Image path is stored in database as - /storage/images/products/4/ACTCMRcYlWR8Bn3ZxoJ7bpiDJ7.png
I had to add remove '/storage' part of the path and prepend '/public'.
$productImage = str_replace('/storage', '', $product->image_path);
Storage::delete('/public' . $productImage);
If you added /storage part to the path you can use file system:
if (File::exists(public_path($image->path))) {
File::delete(public_path($image->path));
}
I would write something like this in my Model or helper and call it whenever I want:
public static function delete_file($path)
{
if (\Storage::disk('public')->exists($path))
\Storage::disk('public')->delete($path);
}

Obtain CodeIgniter links that consider routes.php

How can I link pages in my site considering routes.php?
Example:
$route['login'] = 'user/login';
The code above allows me to see "user/login" visiting just "login". But how can I link to that page using the internal route (user/login) and get as a result the "external route" "login".
I think it's important because I could change my URLs just modifiying "routes.php" and linking everything with internal routes.
From a Drupal perspective I can have my internal route "node/1" and the external url could be "about-us". So if I use "l('node/1')" this will return "about-us". Is there a function like "drupal_get_path_alias"?
Right now I can't find anything in the CI docs that point me to the right direction.
Thanks for your help.
You could have a look at using something like
http://osvaldas.info/smart-database-driven-routing-in-codeigniter
This would allow you to have the routes configured in the database. Then if you want to dynamically create you links through a model like this:
class AppRoutesModel extends CI_Model
{
public function getUrl($controller)
{
$this->db->select('slug');
$this->db->from('app_routes');
$this->db->where('controller', $controller);
$query = $this->db->result();
$data = $query->row();
$this->load->library('url');
return base_url($data->slug);
}
public function getController($slug)
{
$this->db->select('controller');
$this->db->from('app_routes');
$this->db->where('slug', $slug);
$query = $this->db->result();
$data = $query->row();
return $data->controller;
}
}
These have not been fully tested but will hopefully give you the general idea.
I hope this helps you :)
Edit------------------------------
You can create a routes_helper.php and add a function like
//application/helpers/routes_helper.php
function get_route($path)
{
require __DIR__ . '/../config/routes.php';
foreach ($route as $key => $controller) {
if ($path == $controller) {
return $key;
}
}
return false;
}
$this->load->helper('routes');
echo get_route('controller/method');
This does roughly what you want although this method does not support the $1 $2 etc vars that can be added to reflect the :num or :any wildcard that exist. You can edit the function to add that functionality but this will point you in the right direction :D
You can do that with .htaccess file:
Redirect 301 /user/login http://www.example.com/login

How to delete file from public folder in laravel 5.1

I want to delete a News from database and when I hit the delete button all data from database deleted but the image is remains in upload folder.
So, how do I this to work.
thanks
This is my function again but does not delete the image from images/news folder of public directory>
public function destroy($id) {
$news = News::findOrFail($id);
$image_path = app_path("images/news/{$news->photo}");
if (File::exists($image_path)) {
//File::delete($image_path);
unlink($image_path);
}
$news->delete();
return redirect('admin/dashboard')->with('message','خبر موفقانه حذف شد');
}
You could use PHP's unlink() method just as #Khan suggested.
But if you want to do it the Laravel way, use the File::delete() method instead.
// Delete a single file
File::delete($filename);
// Delete multiple files
File::delete($file1, $file2, $file3);
// Delete an array of files
$files = array($file1, $file2);
File::delete($files);
And don't forget to add at the top:
use Illuminate\Support\Facades\File;
Use the unlink function of php, just pass exact path to your file to unlink function :
unlink($file_path);
Do not forget to create complete path of your file if it is not stored in the DB. e.g
$file_path = app_path().'/images/news/'.$news->photo;
this method worked for me
First, put the line below at the beginning of your controller:
use File;
below namespace in your php file
Second:
$destinationPath = 'your_path';
File::delete($destinationPath.'/your_file');
$destinationPath --> the folder inside folder public.
This worked at laravel 8
use File;
if (File::exists(public_path('uploads/csv/img.png'))) {
File::delete(public_path('uploads/csv/img.png'));
}
First, you should go to config/filesystems.php and set 'root' => public_path() like so:
'disks' => [
'local' => [
'driver' => 'local',
'root' => public_path(),
],
Then, you can use Storage::delete($filename);
Update working for Laravel 8.x:
Deleting an image for example ->
First of all add the File Facade at the top of the controller:
use Illuminate\Support\Facades\File;
Then use delete function. If the file is in 'public/' you have to specify the path using public_path() function:
File::delete(public_path("images/filename.png"));
Using PHP unlink() function, will have the file deleted
$path = public_path()."/uploads/".$from_db->image_name;
unlink($path);
The above will delete an image returned by $from_db->image_name located at public/uploads folder
Try to use:
unlink('.'.Storage::url($news->photo));
Look the dot and concatenation before the call of facade Storage.
public function destroy($id) {
$news = News::findOrFail($id);
$image_path = app_path("images/news/".$news->photo);
if(file_exists($image_path)){
//File::delete($image_path);
File::delete( $image_path);
}
$news->delete();
return redirect('admin/dashboard')->with('message','خبر موفقانه حذف شد');
}
First make sure the file exist by building the path
if($request->hasFile('image')){
$path = storage_path().'/app/public/YOUR_FOLDER/'.$db->image;
if(File::exists($path)){
unlink($path);
}
Try it :Laravel 5.5
public function destroy($id){
$data = User::FindOrFail($id);
if(file_exists('backend_assets/uploads/userPhoto/'.$data->photo) AND !empty($data->photo)){
unlink('backend_assets/uploads/userPhoto/'.$data->photo);
}
try{
$data->delete();
$bug = 0;
}
catch(\Exception $e){
$bug = $e->errorInfo[1];
}
if($bug==0){
echo "success";
}else{
echo 'error';
}
}
the easiest way for you to delete the image of the news is using the model event like below
and the model delete the image if the news deleted
at first you should import this in top of the model class use Illuminate\Support\Facades\Storage
after that in the model class News you should do this
public static function boot(){
parent::boot();
static::deleting(function ($news) {
Storage::disk('public')->delete("{$news->image}");
})
}
or you can delete the image in your controller with
this command
Storage::disk('public')->delete("images/news/{$news->file_name}");
but you should know that the default disk is public but if you create folder in the public folder and put the image on that you should set the folder name before $news->file_name
This is the way I upload the file and save it into database and public folder and also the method I delete file from database and public folder.
this may help you and student to get complete source code to get the task done.
uploading file
at the first if you save file into database by giving path public_path() once it not need to used in delete method again
public function store_file(Request $request)
{
if($request->hasFile('file'))
{
$fileExtention = $request->file('file')->getClientOriginalExtension();
$name = time().rand(999,9999).$request->filename.'.'.$fileExtention;
$filePath = $request->file('file')->move(public_path().'/videos',$name);
$video = new Video_Model;
$video->file_path = $filePath;
$video->filename = $request->filename;
$video->save();
}
return redirect()->back();
}
deleting file
from database and public folder as you saved
public function delete_file(Request $request)
{
$file = Video_Model::find($request->id);
$file_path = $file->file_path;
if(file_exists($file_path))
{
unlink($file_path);
Video_Model::destroy($request->id);
}
return redirect()->back();
}
Its a very old thread, but I don't see that the solution is here or the this thread is marked as solved. I have also stuck into the same problem I solved it like this
$path = public_path('../storage/YOUR_FOLDER_NAME/YOUR_FILE_NAME');
if (!File::exists($path))
{
File::delete(public_path('storage/YOUR_FOLDER_NAME/YOUR_FILE_NAME'));
}
The key is that you need to remove '..' from the delete method. Keep in mind that this goes true if you are using Storage as well, whether you are using Storage of File don't for get to use them like
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use File; // For File
use Storage; // For Storage
Hope that it will help someone.
For Delete files from the public folders, we can use the File::delete function into the Laravel. For use File need to use File into the controller OR We can use \File. This consider the root of the file.
// Delete a single file
File::delete($filename);
For delete Multiple files
// Delete multiple files
File::delete($file1, $file2, $file3);
Delete an array of Files
// Delete an array of files
$files = array($file1, $file2);
File::delete($files);
Two ways to delete the image from public folder without changing laravel filesystems config file or messing with pure php unlink function:
Using the default local storage you need to specify public subfolder:
Storage::delete('public/'.$image_path);
Use public storage directly:
Storage::disk('public')->delete($image_path);
I would suggest second way as the best one.
Hope this help other people.
If you store your image in folder public, try this steps:
For example your image is sample.jpg and your path is public/img/sample.jpg
so this codes will delete your image
use Illuminate\Support\Facades\File;
.
.
.
public function deleteImage(){
$imgWillDelete = public_path() . '/img/sample.jpg';
File::delete($imgWillDelete);
}
Follow the steps carefully to get the image first=>
$img = DB::table('students')->where('id',$id)->first();
$image_path = $img->photo;
unlink($image_path);
DB::table('students')->where('id',$id)->delete();
For delete file from folder you can use unlink and if you want to delete data from database you can use delete() in laravel
Delete file from folder
unlink($image_path);
For delete record from database
$flight = Flight::find(1);
$flight->delete();
public function update(Request $request, $id)
{
$article = Article::find($id);
if($request->hasFile('image')) {
$oldImage = public_path($article->image);
File::delete($oldImage);
$fileName = time().'.'.$request->image->extension();
$request->image->move(public_path('uploads/'), $fileName);
$image ='uploads/'.$fileName;
$article->update([
'image' => $image,
]);
}
$article->update([
'title' => $request->title,
'description' => $request->description,
]);
return redirect()->route('admin.article.index');
}
you can delete file and its record like wise:
public function destroy($id)
{
$items = Reports::find($id); //Reports is my model
$file_path = public_path('pdf_uploads').'/'.$items->file; // if your file is in some folder in public directory.
// $file_path = public_path().'/'.$items->file; use incase you didn't store your files in any folder inside public folder.
if(File::exists($file_path)){
File::delete($file_path); //for deleting only file try this
$items->delete(); //for deleting record and file try both
}
return redirect()->back()->with('message','client code: '.$items->receipt_no.' report details has been successfully deleted along with files');
}
note: items->file is my attribute in database where I have stored the name of the file like so,
I have stored the file in the directory "public/pdf_uploads/filename"
Don't forget to add this in your header
use Illuminate\Support\Facades\File;
For File Syntax:
if(File::exists(public_path('upload/test.png'))){
File::delete(public_path('upload/test.png'));
}else{
dd('File does not exists.');
}
For Storage Syntax:
if(Storage::exists('upload/test.png')){
Storage::delete('upload/test.png');
/*
Delete Multiple File like this way
Storage::delete(['upload/test.png', 'upload/test2.png']);
*/
}else{
dd('File does not exists.');
}
Common Method is :
#unlink('/public/admin/pro-services/'.$task->pro_service_image);

Resources