Replace Old image with new image in laravel - laravel

CONTROLLER
public function updateproduct(Request $request, $id)
{
// dd($request->all());
$request->validate([
'name'=>'required',
'description'=>'required',
'price'=>'required|numeric',
'quantity'=>'required|numeric',
]);
$product = Product::where('id', $id)->first();
if(is_null($product)) {
$product = new Product();
}
$product->name=$request->name;
$product->description=$request->description;
$product->price=$request->price;
$product->quantity=$request->quantity;
if($request->hasfile('images')){
$existingimages = Image::where(['product_id'=> $product->id, 'source'=> 1])->get();
if($existingimages->count() > 0)
foreach($existingimages as $existingimage) {
$filename = public_path().'files/'.$existingimage->name;
if(file_exists($filename)){
unlink($filename);
$existingimage->delete();
}
}
foreach($request->file('images') as $file){
$name = rand(1,9999).'.'.$file->getClientOriginalName().$file->getClientOriginalExtension();
if($file->move(public_path().'/files/', $name)){
$updateImage = Image::firstWhere('product_id', $product->id);
$updateImage->images = $name;
$updateImage->source = 1;
$updateImage->save();
}
}
}
Please check updated question. Request you to correct me if I wrong. Right now it only updates 1 image and other images remains same. please help me with this.

Your code is somewhat confusing, I'm afraid.
Your request appears to allow for multiple images to be uploaded. Here :
if(file_exists($imagePath)){
unlink($imagePath);
}
you look like you're trying to delete any images that already exist, but when you store upload images you're assigning them a random name (which Laravel can already handle for you, by the way, so there's no need to do it yourself) so you're unlikely to be actually deleting them because there'll likely be no file at that location anyway.
Nowhere does your code actually delete any existing images from the database. Essentially what you want to do is :
If the upload has images, retrieve all the existing images for that product.
Delete the physical files for those existing images.
Delete the database entries for those existing images.
Upload your new images and save their details to the database.
Translating that into code means :
if($request->hasfile('images')){
// Delete any existing image files and database entries.
$existingimages = Image::where('product_id', $product->id)->get();
if($existingimages->count() > 0)
foreach($existingimages as $existingimage) {
$filename = public_path().'files/'.$existingimage->name;
unlink($filename);
$existingimage->delete();
}
}
// Carry on with your upload
}

It adds new images because you are using the Image::create method. If I understood correctly, you want to modify the images of your products in the image table.
Try to modify your code like :
$updateImage = Image::firstWhere('product_id', $product->id);
$updateImage->images = $name;
$updateImage->source = 1;
$updateImage->save();

Related

is there any possibility to display image from public folder in Laravel controller?

this function returns only one image. but I want to show all images which are stored in this folder. can anyone help me?
My controller
public function index()
{
$get=Resturant::all(['id','name','image']);
foreach ($get as $image) {
$path =public_path().'/Images/Resturants/'.$image->image;
$file= File::get($path);
$type= File::mimeType($path);
$response= Response::make($file, 200);
$response->header("Content-Type",$type);
return $response;
}
}
You don't need to be trying to return a file response, since your web server itself can handle serving files in the public folder. Also you wouldn't be trying to return multiple files (somehow) in the response. You can just return an array of the URLs to the files and let what ever is consuming this make the requests to get these files by URL. This would simplify your controller method quite a bit:
return Resturant::pluck('image')
->map(fn ($i) => asset('Images/Resturants/'. $i));
PHP 8 here, but its pretty simple, just have to make URLs from each image.
If you want to have the names to go along with this you can adjust pluck to use a column for the index:
...pluck('image', 'name')...

Generate multiple PDF documents with loop with dompdf in laravel

I am trying to download multiple pdf using dompdf in laravel, but below solution just concatenate into one pdf file
$weeks = ['test','test2'];
$html = '';
foreach($weeks as $hours)
{
$view = view('contract');
$html .= $view->render();
}
$pdf = PDF::loadHTML($html);
$sheet = $pdf->setPaper('a4', 'landscape');
return $sheet->download('download.pdf');
the server can only return a response, if you want several pdf files you should modify your method so that it accepts some parameter and for each parameter generate a pdf
It is not possible to download more than one file in a single HTTP request.
What you could do is pack the files into o zip and download that. You can try https://github.com/zanysoft/laravel-zip or any other available solution.
Another option would be to save the files and return only paths for the saved files back to the client. Then make a new request and download the file for each of the returned filepaths.
Also if you want to save to separate PDF files you need to move PDF creation into your foreach loop (create a PDF for each parameter).
$weeks = ['test','test2'];
$files = [];
foreach($weeks as $hours)
{
$view = view('contract');
$html = $view->render();
$pdf = PDF::loadHTML($html);
$pdf->setPaper('a4', 'landscape');
$pdf->save('documents/'.$hours.'.pdf');
$files[] = 'documents/'.$hours.'.pdf';
}
return response()->json(['files' => $files]);
In this case the foreach doesn't really do anything other than produce two identical PDF files. If you want to actually apply some kind of changes to your view based on values in $weeks you need to pass that to your view.
$view = view('contract', ['data' => $hours]);
That makes $data available in your view and you can change the resulting PDF in that way (show your contract.blade.php if you need more help regarding that).

How to display file which had already upload laravel 5.2?

I upload file in to my database and moved that file as same name in documents folder in a root path like below :)
public function store(PslCall $call,Request $request)
{
$this->validate($request, $this->rules);
$uploadDestinationPath = base_path() . '/documents/';
$current_id = Document::where('call_id',$call->id)->count()+1;
if ($request->hasFile('file'))
{
$file =$request->file;
$fileName = $file->getClientOriginalName();
$file->move($uploadDestinationPath, $call->id.'_'.$current_id.'_'.$fileName);
}
$input = $request->all();
$input['file'] = $call->id.'_'.$current_id.'_'.$fileName;
$input['call_id'] = $call->id;
Auth::user()->documents()->create($input);
return Redirect::route('calls.documents.index',$call->id)->with('message','You have successfully submitted');
}
its works perfect now im display in my index page all the files like below :)
<td>{{strtoupper($document->title)}}</td>
<td>{{$document->file}}</td>
now my route file i have route to display my file like this :
Route::get('documents/{file}',function() {
return 'hi';
});
here im getting hi output when i click <td>{{$document->file}}</td> this path
but i want know how to display file which i upload same file name ?
As documentation says if you want to display the file content then you may use inside your route function something like:
return response()->file('pathToFile');
If download the file is what you want, then try to use instead:
return response()->download('pathToFile');

Magento importing images

I am getting stuck with images not displaying with their products. When I create a product and insert an image with that product manually through (manage products) the image shows which is great.
However we have over 1000 product images which need to be uploaded, (all the product information is already up I just need to add the images)
I have exported the products CSV file and the working image address is /n/g/image1.jpg
I have then copied that but change the image to image2.jpg, image3.jpg etc. I then uploaded the new images into that folder directory on our server thinking that's enough.
I then upload the CSV file blow the cache and reindex the data however no new images show and worse the working image doesn't display.
I have filled in image, small_image and thumbnail details in the CSV. All images are correctly sized etc.
Further more can allow tell me where I can just have 1 image folder in the directory where all my images are stored?
Thanks
I'm using Magento version 1.7.0.2
First of all your image should store in media>import directory
then in your csv file just write in image column /imagename.jpg
it will find same imagename in import directory, if image exist then it will upload the image
EDIT
if you don't have import directory then simply create it
I'm sorry to say, but there is more going on behind the scenes with magento images that it simply putting a filename in the database and linking to your image. The cache generation alone is pretty complex. I believe you are going to have a hard time doing it the way you are attempting.
That being said, I do have a suggestion. Since your images are already on the server, I suggest you write a simple php script to tell magento to attach them to the product image. This could be automated, but i'll give you a small example below...
To attach an image, you would simply navigate to the url like this
http://yoursite.com/imageattacher.php?sku=YOURSKU&image=yourimagefilename.jpg
The script would be like this... create a file in your magento ROOT and call it imageattacher.php. Upload your images to the magento media import directory. I have not tested this but it should work.
<?php
// Initialize magento for use outside of core
umask(0);
require_once 'app/Mage.php';
Mage::app('admin');
// Get the variables from the URL
$sku = $_GET["sku"];
$imageName = $_GET["image"];
// get the image from the import dir
$import = Mage::getBaseDir('media') . DS . 'import/' . $imageName;
// Load the product by sku
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
// if the product exists, attempt to add the image to it for all three items
if ($product->getId() > 0)
{
// Add the images and set them for their respective usage (the radio button in admin)
$product->addImageToMediaGallery($import,array('image', 'small_image', 'thumbnail'),false,false);
// Make the changes stick
$product->save();
}
?>
See this http://www.danneh.org/2012/05/creating-products-programmatically-magento/
The issue in the end was that there wasn't an import folder under the media directory. The images were uploaded to this folder. The image column in the CSV was changed to /image1.jpg which allowed them to show on the website.
I had to import a bunch of Magento product images recently which were all named by SKU (eg 123456.jpg). This is the script I used to import them, parts of which are based on CarComp's answer. It will only work for numeric SKUs (eg 123456) but could be fairly easily modified to cater for alphanumeric ones.
<?php
require_once(__DIR__ . "/app/Mage.php");
Mage::app('admin');
class Sku_ImageLoader {
private $_uploadDir;
private $_imagePaths;
public function setUploadDirectory($dir = null) {
if (empty($dir)) {
if (isset($this->_uploadDir)) return $this;
$dir = 'upload';
}
$this->_uploadDir = Mage::getBaseDir('media') . DS . $dir;
// mkdir($this->_uploadDir . DS . "/loaded", 0770);
return $this;
}
public function load() {
$this->setUploadDirectory();
// Match product images like 123456.jpg
$pattern = '[0-9][0-9][0-9][0-9][0-9][0-9].{jpg,gif,png}';
chdir($this->_uploadDir);
$this->_imagePaths = glob($pattern, GLOB_BRACE);
return $this;
}
public function showFiles() {
$this->load();
echo "\r\n\r\nSorry, I wasn't able to upload the following image files in " . $this->_uploadDir . "\r\n\r\n<pre>\r\n";
print_r($this->_imagePaths);
return $this;
}
private function _addImage($path) {
$sku = (string)intval($path);
try {
echo "Loading SKU: {$sku} ... ";
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
// if the product exists, attempt to add the image to it for all three items
if (strpos(get_class($product), 'Catalog_Model_Product') !== false && $product->getId() > 0) {
$product->addImageToMediaGallery($path,array('image', 'small_image', 'thumbnail'),false,false);
$product->save();
echo " ok \r\n";
return true;
}
} catch (Exception $e) {
echo "Exception thrown for {$sku}: " . $e->getMessage() . "\r\n";
}
echo " (FAILED) \r\n";
return false;
}
private function _moveImage($path) {
// rename($path, 'loaded' . DS . $path);
unlink($path);
}
public function import() {
echo "<pre>\r\n";
if (!isset($this->_imagePaths)) $this->load();
foreach ($this->_imagePaths as $path) {
if ($this->_addImage($path)) {
$this->_moveImage($path);
}
}
return $this;
}
}
$u = new Sku_ImageLoader();
$u->import()->showFiles();
?>

Magento - re-importing of products

I have a script that pulls in data from a 3rd party file. My import simply parses and inserts rows, which is working fine.
The problem comes with images.
When the import script runs, it first deletes all the current items and then the import begins, inserting all products and images into the gallery.
On the first import, everything is fine, the images go in and I see them on the frontend no problem. The problem comes with everytime I then re-import these products, it doesn't seem to delete all images, as when the products re-import, I see, for example the 4 images correct, then then loads of blank rows, like images should be there, but can't be found.
I don't want to see these blank lines, but I'm not sure why they are there.
Could it be because the images for the product are already in the catalogue?
I am really unsure what and why this is doing what it is.
Thanks
EDIT:
My code is:
require_once('app/Mage.php');
$app = Mage::app('default');
$product = Mage::getSingleton('catalog/product');
$txt_file = file_get_contents('test.txt');
$rows = explode("\n", $txt_file);
array_shift($rows);
foreach($rows as $row => $data)
{
//get row data
$row_data = explode('^', $data);
$info[$row]['uniqueid'] = $row_data[0];
$info[$row]['client'] = $row_data[1];
$info[$row]['make'] = $row_data[2];
$info[$row]['model'] = $row_data[3];
$info[$row]['adtext'] = $row_data[4];
//display images
$row_images = explode(',', $info[$row]['picturereference']);
foreach($row_images as $row_image)
{
$product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import/' . $row_image, array('image', 'small_image','thumbnail'), false, false);
}
$product->setStoreId(Mage::app()->getStore(true)->getWebsite()->getId());
$product->setWebsiteIds(array(Mage::app()->getStore(true)->getWebsite()->getId()));
$product->setId($info[$row]['id']);
$product->setSku(strtolower($info[$row]['make']).'-'.strtolower($info[$row]['model']));
$product->setName($info[$row]['make']);
$product->setDescription($info[$row]['adtext']);
try {
$product->save();
echo "Saved";
}
catch (Exception $ex) {
echo "<pre>".$ex."</pre>";
}
}
Is this because the addImageToMediaGallery is called on each iteration and adding all images to each product?
Thanks
Ok so I figured out my problem
Inside the foreach I moved the call to the getSingleton and I added the the following: $product = Mage::getModel('catalog/product');
I then, after each iteration, unset the following:
unset($product);
unset($info);
unset($stockData);
unset($row_images);
This seemed to fix my script and now imports each products images into the proper product rather than importing other and adding random blank entries
Thanks all
A few files you'll want to examine to break down addImageToMediaGallery and determine what exactly its doing.
app/code/core/Mage/Catalog/Model/Product.php - Contains the method your using, breaking it down more you'll find...
app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Media.php - Contains more of the "bits and pieces" of addImageToMediaGallery like addImage etc.
Some possibilities to try would be either
A) determine if the files already exist and are attached to the product and ignoring them upon a second round of import. Perhaps looking for different file stamp. getMediaGalleryImages within Product.php.
B) clear the media files associated with the products BEFORE importing again? clearMediaAttribute and removeImage within Media.php.
I would also try the $move option set to true within your addImageToMediaGallery call as well.
/**
* Add image to media gallery
*
* #param string $file file path of image in file system
* #param string|array $mediaAttribute code of attribute with type 'media_image',
* leave blank if image should be only in gallery
* #param boolean $move if true, it will move source file
* #param boolean $exclude mark image as disabled in product page view
*/
public function addImageToMediaGallery($file, $mediaAttribute=null, $move=false, $exclude=true)
{
Another option would be to try to specify null for the second param, if you note the PHPDoc comments, leaving it blank will only be for the gallery which sounds like what you are wanting...
foreach($row_images as $row_image)
{
$product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import/' . $row_image, null, false, false);
}
Let me know if any of these help.
Give something like this a try:
//Check if gallery attribute exists then remove all images if it exists
//Get products gallery attribute
$attributes = $product->getTypeInstance()->getSetAttributes();
if (isset($attributes['media_gallery'])) {
$gallery = $attributes['media_gallery'];
//Get the images
$galleryData = $product->getMediaGallery();
foreach($galleryData['images'] as $image){
//If image exists
if ($gallery->getBackend()->getImage($product, $image['file'])) {
$gallery->getBackend()->removeImage($product, $image['file']);
}
}
}
This blog posting may also help, as its where I got the code snippet form also:
http://www.sharpdotinc.com/mdost/2010/03/02/magento-import-multiple-images-or-remove-images-durring-batch-import/

Resources