2

Magento ver.: 2.2.2

I have created custom image attribute. This is displaying perfectly. But when I upload an image and save product, it's not saving. When I have debugged my code, I have found an issue. My image attribute value display null value every time in my model file(Magetest\Test\Model\Attribute\Product\Image).

enter image description here

Here is my code.

app/code/Magetest/Test/Setup/InstallData.php

    <?php
namespace Magetest\Test\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Catalog\Setup\CategorySetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{

    protected $categorySetupFactory;

    public function __construct(
        \Magento\Catalog\Setup\CategorySetupFactory $categorySetupFactory,
        \Magento\Eav\Model\Entity\TypeFactory $eavTypeFactory,
        \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory $attributeFactory,
        \Magento\Eav\Model\Entity\Attribute\SetFactory $attributeSetFactory,
        \Magento\Eav\Model\Entity\Attribute\GroupFactory $attributeGroupFactory,
        \Magento\Eav\Model\AttributeManagement $attributeManagement,
        \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory,
        \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory $groupCollectionFactory
    ) {
        $this->_categorySetupFactory = $categorySetupFactory;
        $this->_eavTypeFactory = $eavTypeFactory;
        $this->_attributeFactory = $attributeFactory;
        $this->_attributeSetFactory = $attributeSetFactory;
        $this->_attributeGroupFactory = $attributeGroupFactory;
        $this->_attributeManagement = $attributeManagement;
        $this->_eavSetupFactory = $eavSetupFactory;
        $this->_groupCollectionFactory = $groupCollectionFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $groupName = 'Custom Product Image Upload';
        $attributes = [
            'custom_product_image' => [
                'type' => 'varchar',
                'backend' => 'Magetest\Test\Model\Attribute\Product\Image',
                'frontend' => '',
                'label' => 'Upload Custom Image',
                'input' => 'image',
                'class' => '',
                'group' => $groupName,
                'source' => '',
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'visible' => true,
                'required' => false,
                'user_defined' => true,
                'default' => null,
                'searchable' => false,
                'filterable' => false,
                'comparable' => false,
                'visible_on_front' => false,
                'used_in_product_listing' => false,
                'unique' => false,
                'apply_to' => '',
                'is_used_in_grid'       => false,
                'is_visible_in_grid'    => false,
                'is_filterable_in_grid' => false
            ]
        ];

        $categorySetup = $this->_categorySetupFactory->create(['setup' => $setup]);

        foreach ($attributes as $code => $params)
            $categorySetup->addAttribute(\Magento\Catalog\Model\Product::ENTITY, $code, $params);

        $this->sortGroup($groupName, 11);
    }

    private function sortGroup($attributeGroupName, $order)
    {
        $entityType = $this->_eavTypeFactory->create()->loadByCode('catalog_product');
        $setCollection = $this->_attributeSetFactory->create()->getCollection();
        $setCollection->addFieldToFilter('entity_type_id', $entityType->getId());

        foreach ($setCollection as $attributeSet)
        {
            $group = $this->_groupCollectionFactory->create()
                ->addFieldToFilter('attribute_set_id', $attributeSet->getId())
                ->addFieldToFilter('attribute_group_name', $attributeGroupName)
                ->getFirstItem()
                ->setSortOrder($order)
                ->save();
        }

        return true;
    }
}

app/code/Magetest/Test/Model/Attribute/Product/Image.php

<?php
namespace Magetest\Test\Model\Attribute\Product;

use Magento\Framework\App\Filesystem\DirectoryList;

class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{

    protected $_uploaderFactory;
    protected $_filesystem;
    protected $_fileUploaderFactory;
    protected $_logger;

    public function __construct(
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
    ) {
        $this->_filesystem = $filesystem;
        $this->_fileUploaderFactory = $fileUploaderFactory;
        $this->_logger = $logger;
    }

    public function beforeSave($object)
    {
        echo $this->getAttribute()->getName();
        //Out Put: custom_product_image
        echo '<br>';
        var_dump($object->getData($this->getAttribute()->getName()));
        //Out Put: NULL
        var_dump($this->getAttribute()->getName() . '_additional_data');
        //Out Put: NULL
        var_dump($object->getData('name'));
        //Out Put: string(16) "Joust Duffle Bag"
        exit;
        $value = $object->getData($this->getAttribute()->getName() . '_additional_data');

        if (empty($value) && empty($_FILES)) {
            return $this;
        }

        if (is_array($value) && !empty($value['delete'])) {
            $object->setData($this->getAttribute()->getName(), '');
            $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
            return $this;
        }

        $path = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath('catalog/product/');

        try {

            $uploader = $this->_fileUploaderFactory->create(['fileId' => $this->getAttribute()->getName()]);
            $uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png']);
            $uploader->setAllowRenameFiles(true);
            $result = $uploader->save($path);

            $object->setData($this->getAttribute()->getName(), $result['file']);
            $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
        } catch (\Exception $e) {
            if ($e->getCode() != \Magento\MediaStorage\Model\File\Uploader::TMP_NAME_EMPTY) {
                $this->_logger->critical($e);
            }
        }

        return $this;
    }
}
  • You can find answer to it here magento.stackexchange.com/questions/170186/… – Shireen N Feb 5 '18 at 9:23
  • @shireen Thanks for replay. It's display in "media image" section. I want to display image upload button in my custom section. Please check my screenshot for more detail. – Vithal Bariya Feb 5 '18 at 9:37
  • @Vithal Bariya any other files used or not, if used share code. – Suresh Chikani Feb 5 '18 at 12:18
  • @SureshChikani Other file is not used, Only use basic module required file like registration.php , Data.php, module.xml etc. – Vithal Bariya Feb 5 '18 at 13:03
  • Even I tried this code, but not saving the image. – Amy Feb 26 '19 at 14:27
0

I believe you are missing the upload action. Check with below steps if anything you have missed.

Step:-1

Create a InstallData.php file on location vendor\Module\Setup

<?php
    namespace Vendor\Module\Setup;

    use Magento\Eav\Setup\EavSetup;
    use Magento\Eav\Setup\EavSetupFactory;
    use Magento\Framework\Setup\InstallDataInterface;
    use Magento\Framework\Setup\ModuleContextInterface;
    use Magento\Framework\Setup\ModuleDataSetupInterface;
    use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;

    /**
     * @codeCoverageIgnore
     */
    class InstallData implements InstallDataInterface
    {
        /**
         * EAV setup factory.
         *
         * @var EavSetupFactory
         */
        private $_eavSetupFactory;
        protected $categorySetupFactory;

        /**
         * Init.
         *
         * @param EavSetupFactory $eavSetupFactory
         */
        public function __construct(EavSetupFactory $eavSetupFactory, \Magento\Catalog\Setup\CategorySetupFactory $categorySetupFactory)
        {
            $this->_eavSetupFactory = $eavSetupFactory;
            $this->categorySetupFactory = $categorySetupFactory;
        }

        /**
         * {@inheritdoc}
         *
         * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
         */
        public function install(
            ModuleDataSetupInterface $setup,
            ModuleContextInterface $context
        ) {
            /** @var EavSetup $eavSetup */
            $eavSetup = $this->_eavSetupFactory->create(['setup' => $setup]);
            $setup = $this->categorySetupFactory->create(['setup' => $setup]);         
            $setup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY, 'custom_image', [
                    'type' => 'varchar',
                    'label' => 'Custom Image',
                    'input' => 'image',
                    'backend' => 'Magento\Catalog\Model\Product\Attribute\Backend\Image',
                    'required' => false,
                    'sort_order' => 9,
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                    'group' => 'General Information',
                ]
            );
        }
    }

Step:-2

Create a product_form.xml file on location Package\Custom_Module\view\adminhtml\ui_component

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="content">
        <field name="custom_image">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="source" xsi:type="string">category</item>
                    <item name="label" xsi:type="string" translate="true">Custom Image</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="formElement" xsi:type="string">fileUploader</item>
                    <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
                    <item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
                    <item name="required" xsi:type="boolean">false</item>
                    <item name="sortOrder" xsi:type="number">40</item>
                    <item name="uploaderConfig" xsi:type="array">
                        <item name="url" xsi:type="url" path="module/product_image/upload"/>
                    </item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

Step:-3

Add below code in Vendor/Module/etc/di.xml

<type name="Vendor\Module\Controller\Adminhtml\Product\Image\Upload">
    <arguments>
        <argument name="imageUploader" xsi:type="object">Magento\Catalog\ProductImageUpload</argument>
    </arguments>
</type>
<virtualType name="Magento\Catalog\ProductImageUpload" type="Magento\Catalog\Model\ImageUploader">
    <arguments>
        <argument name="baseTmpPath" xsi:type="string">catalog/tmp/product</argument>
        <argument name="basePath" xsi:type="string">catalog/product</argument>
        <argument name="allowedExtensions" xsi:type="array">
            <item name="jpg" xsi:type="string">jpg</item>
            <item name="jpeg" xsi:type="string">jpeg</item>
            <item name="gif" xsi:type="string">gif</item>
            <item name="png" xsi:type="string">png</item>
        </argument>
    </arguments>
</virtualType>

Step:-4

Create Upload.php file on location Vendor/Module/Controller/Adminhtml/Product/Image

<?php
namespace Vendor\Module\Controller\Adminhtml\Product\Image;

use Magento\Framework\Controller\ResultFactory;

/**
 * Adminhtml Product Image Upload Controller
 */
class Upload extends \Magento\Backend\App\Action
{
    /**
     * Image uploader
     *
     * @var \Magento\Catalog\Model\ImageUploader
     */
    protected $imageUploader;

    /**
     * Uploader factory
     *
     * @var \Magento\MediaStorage\Model\File\UploaderFactory
     */
    private $uploaderFactory;

    /**
     * Media directory object (writable).
     *
     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
     */
    protected $mediaDirectory;

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * Core file storage database
     *
     * @var \Magento\MediaStorage\Helper\File\Storage\Database
     */
    protected $coreFileStorageDatabase;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    /**
     * Upload constructor.
     *
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Catalog\Model\ImageUploader $imageUploader
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Catalog\Model\ImageUploader $imageUploader,
        \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase,
        \Psr\Log\LoggerInterface $logger
    ) {
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
        $this->uploaderFactory = $uploaderFactory;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
        $this->storeManager = $storeManager;
        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
        $this->logger = $logger;
    }

    /**
     * Check admin permissions for this controller
     *
     * @return boolean
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Vendor_Module::product');
    }

    /**
     * Upload file controller action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('custom_image');
            $result['cookie'] = [
                'name' => $this->_getSession()->getName(),
                'value' => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path' => $this->_getSession()->getCookiePath(),
                'domain' => $this->_getSession()->getCookieDomain(),
            ];
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
    }
}

Try if this helps you!

| improve this answer | |
  • Hello Shireen, Thanks for help. I have try your code But it's not working. Image not saved. – Vithal Bariya Feb 5 '18 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.