In this tutorial, you will learn how to attach a file in product admin form and display attachment in product detail page.
Let's start it by creating custom module.
Find Complete module on Github at Magelearn_Productattachement.
Create folder in
app/code/
Magelearn/ProductattachementStep 1: Create module registration file
Add registration.php file in it:
<?php /** * Copyright © All rights reserved. * See COPYING.txt for license details. */ use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magelearn_Productattachement', __DIR__);Add composer.json file in it:
{ "name": "magelearn/module-Productattachement", "description": "Magento2 attach a file in product admin form and display attachment in product detail page", "type": "magento2-module", "license": "OSL-3.0", "authors": [ { "email": "info@mage2gen.com", "name": "Mage2Gen" }, { "email": "vijaymrami@gmail.com", "name": "vijay rami" } ], "minimum-stability": "dev", "require": {}, "autoload": { "files": [ "registration.php" ], "psr-4": { "Magelearn\\Productattachement\\": "" } } }
Add etc/module.xml file in it:
<?xml version="1.0" ?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magelearn_Productattachement" setup_version="1.0.0">
</module> </config>
Step 2: Create InstallData script to add product attachment attribute
Next, we will create a script to add product attribute. So create an InstallData.php in app/code/Magelearn/Productattachement/Setup directory.
<?php namespace Magelearn\Productattachement\Setup; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\InstallDataInterface; use Magento\Eav\Setup\EavSetupFactory; /** * Class InstallData * @package Magelearn\Productattachement\Setup * * @codeCoverageIgnore */ class InstallData implements InstallDataInterface { /** * @var EavSetupFactory */ protected $_eavSetupFactory; public function __construct( EavSetupFactory $eavSetupFactory ) { $this->_eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { $eavSetup = $this->_eavSetupFactory->create(["setup"=>$setup]); $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'attachment', [ 'group' => 'Product Attachment', 'type' => 'varchar', 'label' => 'Attachment', 'input' => 'file', 'backend' => 'Magelearn\Productattachement\Model\Product\Attribute\Backend\File', 'frontend' => '', 'class' => '', 'source' => '', 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, 'visible' => true, 'required' => false, 'user_defined' => true, 'default' => '', 'searchable' => false, 'filterable' => false, 'comparable' => false, 'visible_on_front' => false, 'unique' => false, 'apply_to' => 'simple,configurable', // applicable for simple and configurable product 'used_in_product_listing' => true ] ); } }Here attachment is product attribute code.
- group: Here we have used Product Attachment in the group. So new attribute created in product admin form will be added in a new tab named Product Attachment.
- type: Here we will define varchar in type. We will save file name in attribute so we need varchar in type.
Step 3: Create backend model file to upload product attachment file and save value in attachment attribute
So create File.php in app/code/Magelearn/ProductAttachment/Model/Product/Attribute/Backend directory
<?php namespace Magelearn\Productattachement\Model\Product\Attribute\Backend; use Magento\Framework\App\Filesystem\DirectoryList; class File extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend { /** * @var \Magento\Framework\Filesystem\Driver\File */ protected $_file; /** * @var \Psr\Log\LoggerInterface */ protected $_logger; /** * @var \Magento\Framework\Filesystem */ protected $_filesystem; /** * @var \Magento\MediaStorage\Model\File\UploaderFactory */ protected $_fileUploaderFactory; /** * Construct * * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory */ public function __construct( \Psr\Log\LoggerInterface $logger, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\Filesystem\Driver\File $file, \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory ) { $this->_file = $file; $this->_filesystem = $filesystem; $this->_fileUploaderFactory = $fileUploaderFactory; $this->_logger = $logger; } public function afterSave($object) { $path = $this->_filesystem->getDirectoryRead( DirectoryList::MEDIA )->getAbsolutePath( 'catalog/product/attachment/' ); $delete = $object->getData($this->getAttribute()->getName() . '_delete'); if ($delete) { $fileName = $object->getData($this->getAttribute()->getName()); $object->setData($this->getAttribute()->getName(), ''); $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName()); if ($this->_file->isExists($path.$fileName)) { $this->_file->deleteFile($path.$fileName); } } if (empty($_FILES['product']['tmp_name'][$this->getAttribute()->getName()])) { return $this; } try { /** @var $uploader \Magento\MediaStorage\Model\File\Uploader */ $uploader = $this->_fileUploaderFactory->create(['fileId' => 'product['.$this->getAttribute()->getName().']']); $uploader->setAllowedExtensions(['pdf']); $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; } }Now you can see the product attachment tab and input type file attribute in a new tab in product admin form.
Now after attaching file and save the product, the file is uploaded in pub/media/catalog/product/attachment directory and file name stored in attachment attribute value.
Step 4: Display product attachment link and delete checkbox after saving product in admin form
But after saving the product in product attachment tab file name is not showing up or how to remove file checkbox is not showing up.
So we will display an anchor tag that contains the file path and we will also add delete checkbox to remove the file in the product attachment tab.
We will use a modifier to add these changes in product attachment tab.
So we will create a di.xml in
app/code/
Magelearn/Productattachement/etc/adminhtml directory.<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="attachment" xsi:type="array"> <item name="class" xsi:type="string">Magelearn\Productattachement\Ui\DataProvider\Product\Form\Modifier\File</item> <item name="sortOrder" xsi:type="number">1000</item> </item> </argument> </arguments> </virtualType> </config>
Next, we will create File.php in
app/code/
Magelearn/Productattachement/Ui/DataProvider/Product/Form/Modifier directory.<?php namespace Magelearn\Productattachement\Ui\DataProvider\Product\Form\Modifier; use Magento\Framework\Stdlib\ArrayManager; use Magento\Store\Model\StoreManagerInterface; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; class File extends AbstractModifier { /** * @var ArrayManager */ protected $arrayManager; /** * @var StoreManagerInterface */ protected $storeManager; /** * @param ArrayManager $arrayManager * @param StoreManagerInterface $storeManager */ public function __construct( ArrayManager $arrayManager, StoreManagerInterface $storeManager ) { $this->arrayManager = $arrayManager; $this->storeManager = $storeManager; } public function modifyMeta(array $meta) { $fieldCode = 'attachment'; $elementPath = $this->arrayManager->findPath($fieldCode, $meta, null, 'children'); $containerPath = $this->arrayManager->findPath(static::CONTAINER_PREFIX . $fieldCode, $meta, null, 'children'); if (!$elementPath) { return $meta; } $mediaUrl = $this->storeManager->getStore() ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); $attachementUrl = $mediaUrl . 'catalog/product/attachment/'; $meta = $this->arrayManager->merge( $containerPath, $meta, [ 'children' => [ $fieldCode => [ 'arguments' => [ 'data' => [ 'config' => [ 'elementTmpl' => 'Magelearn_Productattachement/elements/file', 'attachment_url' => $attachementUrl ], ], ], ] ] ] ); return $meta; } /** * {@inheritdoc} */ public function modifyData(array $data) { return $data; } }
app/code/Magelearn/Productattachement/view/adminhtml/web/template/elements
diectory.
Step 5: Display product attachment in product detail page in frontend
Next, we will create a new product attachment tab in the product detail page and will show product attachment for that product.
So next we will create a catalog_product_view.xml in
app/code/Magelearn/Productattachement/view/frontend/layout
directory.
As we have defined in layout file we will create block and phtml file. So next we will create an Downloads.php inProduct Attachment
app/code/Magelearn/Productattachement/Block/Product/
directory.
<?php namespace Magelearn\Productattachement\Block\Product; use Magento\Framework\View\Element\Template; /** * Class:Downloads * Magelearn\Productattachement\Block * * @author Sebwite * @package Magelearn\Productattachement * @copyright Copyright (c) 2015, Sebwite. All rights reserved */ class Downloads extends Template { /** * @var \Magento\Framework\Registry */ private $coreRegistry; /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Framework\Registry $coreRegistry */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Framework\Registry $coreRegistry, \Magento\Store\Model\StoreManagerInterface $storeManager ) { $this->coreRegistry = $coreRegistry; $this->_storeManager = $storeManager; parent::__construct($context); } /** * Return Downloads * * @return mixed */ public function getProductAttachment() { return $this->getProduct()->getAttachment(); } /** * Return current product instance * * @return \Magento\Catalog\Model\Product */ public function getProduct() { return $this->coreRegistry->registry('product'); } /** * * @return string */ public function getAttachmentUrl() { // @TODO - index.php weghalen $mediaUrl = $this ->_storeManager-> getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA ); return $mediaUrl . 'catalog/product/attachment/' . $this->getProduct()->getAttachment(); } }Next we will create a downloads.phtml in
app/code/Magelearn/Productattachement/view/frontend/templates
directory.
<?php $product = $block->getProduct(); //$product_attachment = $product->getAttachment(); $product_attachment = $block->getProductAttachment(); ?> <?php if(!empty($product_attachment)) : ?> <?php endif; ?>Now flush cache and open product detail page. Now you can see the product attachment tab.
Tag :
Magento2,
Magento2 Extensions
0 Comments On "How to attach a file in product admin form and display attachment in product detail page in Magento 2?"