Problem
I'm working on an integration with Magento which first removes all images from a product and then add new ones. The problem is that when I add them the 'thumbnail', 'small_image' and 'image' only gets set on the default store and not the individual stores.
Code
public function setProductImages($entityId, $images, $websiteIds, $removeFirst = true){
$product = Mage::getModel('catalog/product')->load($entityId);
if($removeFirst){
//First I need to reset image selection before I can remove all images
$values = array(
'image' => 'no_selection',
'small_image' => 'no_selection',
'thumbnail' => 'no_selection'
);
//Go through all sites and stores and set the image selection values
foreach($websiteIds as $websiteId) {
$website = Mage::getModel('core/website')->load($websiteId);
foreach ($website->getStoreIds() as $storeId) {
Mage::getSingleton('catalog/product_action')->updateAttributes(array($product->getId()), $values, $storeId);
}
}
//Set the selection values on admin store
Mage::getSingleton('catalog/product_action')->updateAttributes(array($product->getId()), $values, 0);
//Remove all images on product
$mediaGalleryAttribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode($product->getEntityTypeId(), 'media_gallery');
$gallery = $product->getMediaGalleryImages();
foreach ($gallery as $galleryImage) {
$imageFile = $galleryImage->getFile();
$mediaGalleryAttribute->getBackend()->removeImage($product, $imageFile);
}
$product->save();
}
foreach($images as $image) {
file_put_contents($path . DS . $image->filename, $image->content);
$type = in_array($image->name, array('image', 'small_image', 'thumbnail')) ? $image->name : null;
$product->addImageToMediaGallery($path . DS . $image->filename, $type, true, false);
}
$product->save();
}
Is there some way to tell addImageToMediaGallery to set on an array of stores? Or am I missing something?
Solved it by replacing
foreach($images as $image) {
file_put_contents($path . DS . $image->filename, $image->content);
$type = in_array($image->name, array('image', 'small_image', 'thumbnail')) ? $image->name : null;
$product->addImageToMediaGallery($path . DS . $image->filename, $type, true, false);
}
$product->save();
with this:
$imageTypes = array();
//Sets images on default store for product
foreach($images as $image){
file_put_contents($path . DS . $image->filename, $image->content);
$type = in_array($image->name, array('image', 'small_image', 'thumbnail')) ? $image->name : null;
$product->addImageToMediaGallery($path . DS . $image->filename, $type, true, false);
//Store image, small_image and thumbnail for later use
$imageTypes['image'] = $product->getImage();
$imageTypes['small_image'] = $product->getSmallImage();
$imageTypes['thumbnail'] = $product->getThumbnail();
}
$product->save();
//Go through all stores and set image, small_image and thumbnail
foreach($websiteIds as $websiteId) {
$website = Mage::getModel('core/website')->load($websiteId);
foreach($website->getStoreIds() as $storeId) {
Mage::app()->setCurrentStore($storeId);
Mage::getSingleton('catalog/product_action')->updateAttributes(array($product->getId()), $imageTypes, $storeId);
}
}
$product->save();
Related
When I update the database, it uploads a single image. How do I upload multiple?
$id = $this->request->getPost('id');
$model = new UrunModel();
$file = $this->request->getFile('resim');
$resim_eski = $model->find($id);
if($file->isValid() && !$file->hasMoved()){
$eski_resim = $resim_eski['resim'];
if(file_exists("dosyalar/uploads".$eski_resim)){
unlink("dosyalar/uploads".$eski_resim);
}
$imagename = $file->getRandomName();
$file->move("dosyalar/uploads", $imagename);
}else{
$imagename = $resim_eski['resim'];
}
if ($this->request->getFileMultiple('images')) {
foreach($this->request->getFileMultiple('images') as $res)
{
$res->move(WRITEPATH . 'dosyalar/uploads');
$data=[
'baslik' => $this->request->getPost('baslik'),
'slug' => mb_url_title($this->request->getPost('baslik'), '-', TRUE),
'kisa_aciklama' => $this->request->getPost('kisa_aciklama'),
'kategori' => $this->request->getPost('kategori'),
'query_kategori' => $this->request->getPost('query_kategori'),
'aciklama' => $this->request->getPost('aciklama'),
'fiyat' => $this->request->getPost('fiyat'),
'indirimli_fiyat' => $this->request->getPost('indirimli_fiyat'),
'resim' => $imagename,
'resimler' => $res->getClientName(),
'type' => $res->getClientMimeType()
];
$model -> update($id,$data);
}
}
return redirect()->to(base_url('yonetim/urunler'));
}
Controller code above, I've been struggling for 2 days, I couldn't manage it somehow.
When I run the code, it just adds 1 image to each product. I want to add more than one image to 1 product for the gallery part. Any suggestions for this code or a different solution?
function add()
{
$length = count($_FILES['image']['name']);
$filename = $_FILES['image']['name'];
$tempname = $_FILES['image']['tmp_name'];
$allimage = array();
foreach($filename as $key =>$value)
{
move_uploaded_file($tempname[$key],'media/uploads/mobile_product/'.$filename[$key]);
$allimage[] = $filename[$key];
}
if(!empty($allimage))
{
$allimage = json_encode($allimage);
}
else
{
$allimage = '';
}
$data['image'] = $allimage;
$this->db->insert('table',$data);
}
CI4 Controller:
if($this->request->getFileMultiple('image_files')) {
$files = $this->request->getFileMultiple('image_files');
foreach ($files as $file) {
if ($file->isValid() && ! $file->hasMoved())
{
$newNames = $file->getRandomName();
$imageFiles = array(
'filename' => $newNames
);
$modelName->insert($imageFiles );
$file->move('uploads/', $newNames);
}
}
}
HTML
<input type="file" name="image_files[]">
This is the shortest way to do that
I am trying to save the image using faker in the storage folder. I want to keep the images inside the property ID folder. I have tried the below code but it is not working. It hangs the command prompt. The properties have multiple images and are a one-to-many relation. The code below is for the PropertyImageFactory class.
public function definition()
{
$property_id = $this->create(Property::class)->id;
return [
'name' => $this->faker->image(storage_path('app/property-images/'.$property_id), 200, 200, 'cats'),
'sort_order' => $this->faker->numberBetween(1, 10),
'created_at' => now(),
'updated_at' => now(),
];
}
Laravel documentation has 'user_id' => User::factory(), I can't use this because it returns an object and I can't concatenate to string.
Below is the code for the property seeder.
public function run()
{
Property::factory()
->has(Category::factory()->count(3))
->has(PropertyImage::factory()->count(3), 'images')
->count(5)
->create();
}
Laravel documentation has 'user_id' => User::factory(), I can't use this because it returns an object and I can't concatenate to string.
Yup, that will return a UserFactory object just as Property::factory() will return a PropertyFactory. What you want to do is call the create() method on the factory and get the id from the record that is created.
$proprty_id = (\App\Models\Property::factory()->create())->id;
Laravel extracts the ID from the SomeModel::factory(), that's all the magic of Laravel. To do this, you need to properly describe the SomeModelFatory. You can use: $property_id = Property::factory();
As far as I know faker->image no longer works, I can advise using an auxiliary class for image formation.
<?php
namespace App\Helpers;
use Faker\Factory;
use Illuminate\Support\Facades\File;
class Image
{
public static function imageUrl(
int $width = 640,
int $height = 480,
bool $randomizeColors = false,
bool $randomizeTxt = false,
string $format = 'jpg'
): string
{
$baseUrl = "https://dummyimage.com";
$size = "/{$width}x{$height}";
$colors = "/aaa/fff";
$format = '.' . preg_replace('~^\b(?:jpg|png|gif)$~', 'jpg', $format);
if ($randomizeColors) {
$backgroundColor = str_replace('#', '', Factory::create()->safeHexColor);
$foreColor = str_replace('#', '', Factory::create()->safeHexColor);
$colors = "/{$backgroundColor}/{$foreColor}";
}
return $baseUrl . $size . $colors . $format . ($randomizeTxt ? '&text=' . Factory::create()->word : '');
}
public static function fake(
string $dir = null,
int $width = 640,
int $height = 480,
bool $randomizeColors = false,
bool $randomizeTxt = false,
string $format = 'jpg',
bool $fullPath = false
)
{
$dir = is_null($dir) ? sys_get_temp_dir() : $dir;
if (!is_dir($dir) || !is_writable($dir)) {
throw new \InvalidArgumentException("Unable to write to directory $dir");
}
$name = md5(uniqid(empty($_SERVER['SERVER_ADDR']) ? '' : $_SERVER['SERVER_ADDR'], true));
$filename = $name . ".$format";
$filepath = $dir . DIRECTORY_SEPARATOR . $filename;
$url = static::imageUrl($width, $height, $randomizeColors, $randomizeTxt, $format);
try {
$image = file_get_contents($url, false, stream_context_create(['http' => ['timeout' => 10]]));
try {
if (!File::put($filepath, $image)) {
return false;
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
return $fullPath ? $filepath : $filename;
}
}
and use:
public function definition()
{
$property_id = Property::factory();
$dir = storage_path('app' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . $property_id);
mkdir($dir, 755);
return [
'name' => (\App\Helpers\Image())->fake($dir, 200, 200),
'sort_order' => $this->faker->numberBetween(1, 10)
];
}
I have this php code that is supposed to backup an image /optimise the image and the reupload the image to shopify
It works but for a few images before it timesout because there are a lot of images and each image several processes.
There are more than 500 images. Any way I can process all these images without the script timesout?
Here is the code
<?php
//ini_set("display_errors", 1);
//error_reporting(E_ALL);
ini_set('memory_limit', '-1');
require_once("inc/functions.php");
require_once("lib/Tinify/Exception.php");
require_once("lib/Tinify/ResultMeta.php");
require_once("lib/Tinify/Result.php");
require_once("lib/Tinify/Source.php");
require_once("lib/Tinify/Client.php");
require_once("lib/Tinify.php");
\Tinify\setKey("xxxxxxxxx");
$requests = $_GET;
//$hmac = $_GET['hmac'];
$serializeArray = serialize($requests);
$requests = array_diff_key($requests, array('hmac' => ''));
ksort($requests);
$token = "xxxxxx";
$shop = "xxxxx"; //no 'myshopify.com' or 'https'
$storeURL = "https://" . $shop . ".myshopify.com";
$path = realpath("images");
if ( ! is_dir($path)) {
mkdir('images', 0777);
}
$i = 1;
do {
if ($i == 1) {
$date = '2040-01-01T12:00:00-00:00';
}
$array = array('limit' => '250', 'order' => 'created_at desc', 'created_at_max' => $date);
$products = shopify_call($token, $shop, '/admin/api/2020-01/products.json', $array, 'GET');
$products = json_decode($products['response'], JSON_PRETTY_PRINT);
$i++;
foreach ($products['products'] as $product) {
$date = $product['created_at'];
foreach ($product['images'] as $image) {
$image_id = $image['id'];
$image_tag = $image['alt'];
$image_position = $image['position'];
/* Process 1: download and save image (Backup) */
$path = realpath('images/' . $product['id']);
if ( ! is_dir($path)) {
mkdir('images/' . $product['id'], 0777);
}
$fileurl = $image['src'];
$fileName = basename($image['src']);
$names = explode('?v=', $fileName);
file_put_contents('images/' . $product['id'] . '/' . $names[0], file_get_contents($image['src']));
/* End Process 1 */
/* Process 2: Optimise and save optimised Image */
$source = \Tinify\fromUrl($fileurl);
$path = realpath('images/' . $product['id'] .'/optimized');
if ( ! is_dir($path)) {
mkdir('images/' . $product['id'] .'/optimized', 0777);
}
$source->toFile("images/" . $product['id'] . "/optimized/". $names[0]);
/* End Process 2 */
$image = array(
"image" => array(
"id" => $image_id,
)
);
/* Process 3: Delete image from shopify */
$delete_image = shopify_call($token, $shop, "/admin/products/" . $product['id'] . "/images/".$image_id .".json", $image, 'DELETE');
$deleted = $delete_image['response'];
/* End Process 3 */
/* Process 4: Upload Optimised image to shopify */
$imgurl = "http://xxxx/vendor/images/" . $product['id'] . "/optimized/". $names[0];
$upload_image = array(
"image" => array(
"position"=>$image_position,
"alt"=> $image_tag,
"src"=> $imgurl
)
);
$upimage = shopify_call($token, $shop, "/admin/products/" . $product['id']. "/images.json", $upload_image, 'POST');
$uploaded = $upimage['response'];
/* End Process 4 */
}
}
} while (count($products['products']) == 250);
Any advice is highly appreciated. Thanks
In my property section I have two property types:
Freemium
Premium
I want to restrict users to upload only 5 images for Freemium property type while for Premium properties a user can upload infinitive number images and videos.
Must needed some suggestions.
Here is my image upload part :
public function postProperty(PropertyRequest $request)
{
$user = User::where('id', $request->user->user_id)->first();
if(!empty($user))
{
$data['user_id'] = $user->id;
$data['type'] = $request->type;
$data['category'] = $request->category;
$data['area'] = $request->area;
$data['price'] = $request->price;
$data['description'] = $request->description;
//dd($data);
$property = Property::create($data);
//$property['flag'] = false; // if (flag = false, property = freemium) else (flag = true, property = premium ))
$urls = new PropertyImage();
if ($request->hasFile('url'))
{
$files = $request->file('url');
foreach($files as $file)
{
$mime = $file->getMimeType();
//$property['flag'] = $property->account == 1 ? false : true;
if($mime == 'image/jpeg')
{
$fileName = $file->getClientOriginalName();
$destinationPath = public_path() . '/images/';
$file->move($destinationPath, $fileName);
$urls->url = '/public/images/' . $fileName;
$url_data = [
'property_id' => $property->id,
'url_type' => 1,
'url' => $urls->url,
];
$urls->create($url_data);
}
elseif($mime == 'video/mp4')
{
$fileName = $file->getClientOriginalName();
$destinationPath = public_path() . '/videos/';
$file->move($destinationPath, $fileName);
$urls->url = '/public/videos/' . $fileName;
$url_data = [
'property_id' => $property->id,
'url_type' => 2,
'url' => $urls->url,
];
$urls->create($url_data);
}
}
}
return Utility::renderJson(trans('api.success'), true, $property, $urls );
}
}
You can use laravel validation to restrict user to some number of files as shown below
//If user is Freemium then restrict him
if (!$property['flag']) {
$messages = [
"url.max" => "files can't be more than 3."
];
$this->validate($request, [
'url' => 'max:3',
],$messages);
}
Profile image won't upload in database. It get's uploaded in folder, but in database it just says NULL.
Code:
if (Input::exists()) {
if (Token::check(Input::get('token'))) {
try {
$user->update(array(
'image' => $title
));
if (isset($_FILES["image"])) {
$title = date("dmyHms") . "_" . $_FILES["image"]["name"];
$path = "img/profile/" . $_POST["id"] . "_" . $title;
move_uploaded_file($_FILES["image"]["tmp_name"], $path);
}
} catch (Exception $e) {
die($e->getMessage());
}
}
}
Form:
This is solution, it saves image in database:
$user->update(array(
'image' => 'image',
'image' => $title
));