Return image path in Laravel API resource - php

I am build a laravel 5.8 API only application and want to return the image path as path of an API resource so that it can be consumed inside an image source attribute. So this is what I have to done to achieve this.
1. I ran php artisan storgae:link command to create the symbolic link from public/storage to storage/app/public
First I store the image inside a productImages table when a new product is successfully created like this
public function store(Request $request)
{
// create & store the product
if ($product = Product::create([
'name' => $request->name,
'category' => $request->category,
'status' => $request->status,
'price' => $request->price,
'interest' => $request->interest,
])) {
// store the product image
$file = $request->file('image');
$destinationPath = "public/images/products";
$filename = 'pramopro_' . $product->name . '_' . $product->id . '.' . $file->extension();
Storage::putFileAs($destinationPath, $file, $filename);
ProductImage::create([
'product_id' => $product->id,
'name' => $filename
]);
}
// return new product
return new ProductResource($product);
}
Return the image path in the ProductResource like this
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'category' => $this->category,
'status' => $this->status,
'price' => $this->price,
'interest' => $this->interest,
'hidden' => $this->hidden,
'imageUrl' => asset('images/products/' . $this->image->name)
];
}
Testing it on my local serve I get a path like this
{
"id": 1,
"name": "dpk",
"category": "fuel",
"status": "open",
"price": 100000,
"interest": 0.2,
"hidden": 0,
"imageUrl": "http://localhost:8000/images/products/pramopro_dpk_1.jpeg"
}
When I try to view the image by putting http://localhost:8000/images/products/randomtext_1.jpeg in my browser, I get 404 not found error.
But this http://localhost:8000/storage/images/products/pramopro_dpk_1.jpeg displays the image as expected.
How should I be retrieving the image path for it to work?

the asset() function puts you in your public directory, you need to add /storage to the path of your file , try this in your toArray function
'imageUrl' => asset('storage/images/products/' . $this->image->name)
Personal note , handling media in laravel can be a headache i personally use LaravelMediaLibrary by spaite
https://github.com/spatie/laravel-medialibrary
it has really helped me and made handling media as easy as it can get especially when handling multiple media for the same model

Related

Laravel Nova Image Storage Name Issue

So, I am trying to store an image that is uploaded through a blog post to a specific folder with its original file name.
The image is saved to the correct file path already but it's saving it as a random string name. My code is below:
public function fields(Request $request)
{
return [
ID::make('id')->sortable(),
Text::make('URL ID', 'id')->hideFromIndex(),
Text::make('Title', 'title'),
select::make('Market Type', 'market_id')->options([
'church' => 'Church',
'school' => 'School',
'business' => 'Business',
'municipal' => 'Municipal'
]),
Trix::make('Body', 'text'),
Image::make('Image', 'main_image')
->disk('blog')
->storeOriginalName('main_image')
->maxWidth(200)
->prunable(),
];
}
->storeOriginalName() is not about name of the saved file, but name of file that browser gets when clicking 'download' in the image field in detail page
Changing file names most simply can be done with ->store() method, something like this:
Image::make('Image', 'main_image')
->store(function (Request $request, $model) {
$filename = $request->main_image->getClientOriginalName();
$request->main_image->storeAs('/', $filename, 'blog');
return [
'main_image' => '/' . $filename,
'main_image_name' => $request->main_image->getClientOriginalName()
];
})
->maxWidth(200)
->storeOriginalName('main_image_name')
->prunable(),

Laravel blade image display

can someone help me with image display in laravel blade?
So this is full image URL after upload
http://webshop.local/uploads/products/1592949903recommend.png
It is supposed to be uploaded to
public/uploads/products
folder.
Here is part of code where I create product (ProductsController):
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'price' => 'required',
'description' => 'required',
'productImage' => 'required|image'
]);
$productImage = $request->productImage;
$productImage_new_name = time() . $productImage->getClientOriginalName();
$productImage->move('uploads/products' . $productImage_new_name);
Product::create([
'title' => $request->title,
'productImage' => '/uploads/products/' . $productImage_new_name,
'price' => $request->price,
'description' => $request->description
]);
return redirect()->route('products.index');
}
Also here is blade display:
<th><img src="{{ $product->productImage }}" alt="{{ $product->title }} image"></th>
And this is getting me right link because of:
public function getProductImageAttribute($productImage){
return asset($productImage);
}
in product model.
EDIT
When I upload new image it does not go into folder instead it just create new folder with the name of the image and inside it is file with name phpSOMETHING_RANDOM_HERE.tmp
If anyone else faces this problem please check this part of your code.
$productImage = $request->productImage;
$productImage_new_name = time() . $productImage->getClientOriginalName();
$productImage->move('uploads/products', $productImage_new_name);
Specifically this line:
$productImage->move('uploads/products', $productImage_new_name);
The whole time I had dot between path and variable for the name of an uploaded file.
So to fix this problem just change dot for coma.
Instead of
$productImage->move('uploads/products' . $productImage_new_name);
You need
$productImage->move('uploads/products', $productImage_new_name);
In your store method
$path = $request->productImage->store('uploads/products');
// OR if you need to give it name
$path = $request->productImage->storeAs('uploads/products', 'filename.jpg');
You can 'productImage' => $path, while creating product.

Upload multiple images to woo commerce in php

I have a site that uses php to upload product information to woo commerce. everything works fine; however i am now stuck trying to work out how to add multiple images. I have got it adding 1 image fine as seen below
$imageURL = "https://www.[website].co.uk/new/wp-content/uploads/products/";
$imageURL = $imageURL . $product->ITEMNO . ".JPG";
if (!(false === file_get_contents($imageURL,0,null,0,1))) {
$data['images'] = [[
'name' => $product->DESC,
'src' => $imageURL,
'alt' => $product->DESC
]];
echo "Image URL: " . $imageURL . "\n";
}
$woocommerce->put('products/'.$searched[0]->id, $data);
If i try adding in another image using $data['image'] = ... with different data; it just overwrites the image
Im assume EITHER theres a different input for adding it to the product gallery instead of just the main product image. but i couldnt see one at https://woocommerce.github.io/woocommerce-rest-api-docs/?php#product-images-properties
OR if its to do with different id's for the image. Of which i tried adding 'id' => 56565656, to the $data['images'] but it just crashed on me.
Any help would be appreciated.
From woo commerce docs, 'images' is an array type; so it was just figuring out how to write it to get the 2nd image in the second slot of the array; find below the answer
$data['images'] =
[
[
'name' => $product->DESC,
'src' => $imageURL,
'alt' => $product->DESC
],
[
'name' => $product->DESC2,
'src' => $imageURL2,
'alt' => $product->DESC2
]
];

Why is my image not storing in a specified folder in Laravel 5.6?

In my form, I asked for an image to upload. Then I already validated it and it works. But the file is not stored in the uploads folder.
Here's a snippet of my ProductController:
public function store(Request $request)
{
// Validate fields
$this->validate($request, [
'product_name' => 'required',
'product_price' => 'required',
'product_desc' => 'required',
'product_img' => 'image|required'
]);
// Upload image
if($request->hasFile('image')) {
app()->make('path.public/uploads');
$image = $request->image;
$image->move('uploads', $image->getClientOriginalName());
}
/*// Save the data into database
Product::create([
'name' => $request->product_name,
'price' => $request->product_price,
'description' => $request->product_desc,
'image' => $request->image->getClientOriginalName()
]);
// Echo a session message
$request->session()->flash('msg', 'Your product has been added');
// Redirect to view page
return redirect('/products');*/
}
I already tried looking at other possible solutions but the other questions were already at storing the image in the database. I also tried checking if uploads was a directory and existed, and it is.
Can anyone please help? Thanks.
Try this: official documentation: This is how it should look in your controller:
if($request->hasFile('image')) {
$request->file('image')->store('uplodads/', 'public');
}
This would store the image in /storage/app/public/uploads by default. You can also change the public path in /config/filesystems.php. You can then access the file (if you linked the storage) with asset('storage/uploads'.$img_name).
app()->make('path.public/uploads');
I've already solved it. The variable was wrong all along. Instead of it being product_img, I placed image.
Here's the updated code:
// Validate fields
$this->validate($request, [
'product_name' => 'required',
'product_price' => 'required',
'product_desc' => 'required',
'product_img' => 'image|required'
]);
// Upload image
if($request->hasFile('product_img')) {
$image = $request->product_img;
$image->move('uploads', $image->getClientOriginalName());
}

Downloading files using media view in CakePHP

I want to download 4 different files through 4 different links. I am using the Media view to download the files, but I have to hardcode the file name in the download functions in the controller:
function download () {
$this->view = 'Media';
$params = array(
'id' => 'example.zip',
'name' => 'example',
'download' => true,
'extension' => 'zip',
'path' => APP . 'files' . DS
);
$this->set($params);
}
This works fine for one file. Now, for links number 2,3,4, do I need to create 3 different actions and give different file names in them, or is there a way in which I can use download() to only download the respective file depending on which link has been clicked?
That's what variables are for. Generic example:
function download($fileId) {
$file = // find the file you want to serve based on $fileId
$pathInfo = pathinfo($file['path']);
$this->view = 'Media';
$params = array(
'id' => $file['name'],
'name' => $pathInfo['filename'],
'extension' => $pathInfo['extension'],
'download' => true,
'path' => APP . 'files' . DS
);
$this->set($params);
}
In CakePhp 2.x you will get error The view for YourController::download() was not found.
Use viewClass field in CakePHP 2.x:
$this->viewClass = 'Media';
See Media Views — CakePHP Cookbook v2.x documentation
UPD: Media Views are deprecated since CakePHP 2.3, and CakeResponse::file() should be used:
$this->response->file($file['path'], array('download' => true, 'name' => 'foo'));
return $this->response;

Categories