You need to create a class to handle your image upload field and show the image once is uploaded.
So create [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper\Image
class
<?php
namespace [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper;
use Magento\Framework\Data\Form\Element\Image as ImageField;
use Magento\Framework\Data\Form\Element\Factory as ElementFactory;
use Magento\Framework\Data\Form\Element\CollectionFactory as ElementCollectionFactory;
use Magento\Framework\Escaper;
use [Namespace]\[Module]\Model\[Entity]\Image as [Entity]Image;
use Magento\Framework\UrlInterface;
/**
* @method string getValue()
*/
class Image extends ImageField
{
/**
* image model
*
* @var \[Namespace]\[Module]\Model\[Entity]\Image
*/
protected $imageModel;
/**
* @param [Entity]Image $imageModel
* @param ElementFactory $factoryElement
* @param ElementCollectionFactory $factoryCollection
* @param Escaper $escaper
* @param UrlInterface $urlBuilder
* @param array $data
*/
public function __construct(
[Entity]Image $imageModel,
ElementFactory $factoryElement,
ElementCollectionFactory $factoryCollection,
Escaper $escaper,
UrlInterface $urlBuilder,
$data = []
)
{
$this->imageModel = $imageModel;
parent::__construct($factoryElement, $factoryCollection, $escaper, $urlBuilder, $data);
}
/**
* Get image preview url
*
* @return string
*/
protected function _getUrl()
{
$url = false;
if ($this->getValue()) {
$url = $this->imageModel->getBaseUrl().$this->getValue();
}
return $url;
}
}
then create the class that will help you retrieve the image upload path and upload dir
<?php
namespace [Namespace]\[Module]\Model\[Entity];
use Magento\Framework\UrlInterface;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;
class Image
{
/**
* media sub folder
* @var string
*/
protected $subDir = '[namespace]/[module]/[entity]';
/**
* url builder
*
* @var \Magento\Framework\UrlInterface
*/
protected $urlBuilder;
/**
* @var \Magento\Framework\Filesystem
*/
protected $fileSystem;
/**
* @param UrlInterface $urlBuilder
* @param Filesystem $fileSystem
*/
public function __construct(
UrlInterface $urlBuilder,
Filesystem $fileSystem
)
{
$this->urlBuilder = $urlBuilder;
$this->fileSystem = $fileSystem;
}
/**
* get images base url
*
* @return string
*/
public function getBaseUrl()
{
return $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]).$this->subDir.'/image';
}
/**
* get base image dir
*
* @return string
*/
public function getBaseDir()
{
return $this->fileSystem->getDirectoryWrite(DirectoryList::MEDIA)->getAbsolutePath($this->subDir.'/image');
}
}
now in your edit for tab add this in the method _prepareForm
right after declaring the fieldset
$fieldset->addType('image', '\[Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper\Image');
and add your image field like this
$fieldset->addField(
'image_field_name',
'image',
[
'name' => 'image_field_name',
'label' => __('Image field Label'),
'title' => __('Image field Label'),
]
);
In the controller that saves your entity you need to inject in the constructor the following classes
Magento\MediaStorage\Model\File\UploaderFactory
and [Namespace]\[Module]\Model\[Entity]\Image
So make your class look like this
<?php
use Magento\Framework\Exception\LocalizedException as FrameworkException;
class ....
protected $uploaderFactory;
protected $imageModel;
public function __construct(
....
\Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
\[Namespace]\[Module]\Model\[Entity]\Image $imageModel,
....
){
...
$this->uploaderFactory = $uploaderFactory;
$this->imageModel = $imageModel;
...
}
Now, in the same controller add this, before calling $[entity]->save()
$imageName = $this->uploadFileAndGetName('image_field_name', $this->imageModel->getBaseDir(), $data);
$[entity]->setImageFieldName($imageName);
and create this method:
public function uploadFileAndGetName($input, $destinationFolder, $data)
{
try {
if (isset($data[$input]['delete'])) {
return '';
} else {
$uploader = $this->uploaderFactory->create(['fileId' => $input]);
$uploader->setAllowRenameFiles(true);
$uploader->setFilesDispersion(true);
$uploader->setAllowCreateFolders(true);
$result = $uploader->save($destinationFolder);
return $result['file'];
}
} catch (\Exception $e) {
if ($e->getCode() != \Magento\Framework\File\Uploader::TMP_NAME_EMPTY) {
throw new FrameworkException($e->getMessage());
} else {
if (isset($data[$input]['value'])) {
return $data[$input]['value'];
}
}
}
return '';
}
A full example on how to create an entity that supports image and file upload (it's a bit different than described here as it contains an extra class for upload) can be found here
Finally i have resolve my issue .
Only Need to override Subscriber.
I am posting my entire code. may be it will helpful to someone.
di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Newsletter\Model\Subscriber" type="Navin\Subscribe\Model\Subscriber" />
</config>
Subscriber.php Model Files
namespace Navin\Subscribe\Model;
class Subscriber extends \Magento\Newsletter\Model\Subscriber {
/**
* Initialize resource model
*
* @return void
*/
public function subscribe($email, $subscriber_name = '', $subscriber_date_of_birth = '', $subscriber_country_code = '') {
$this->loadByEmail($email);
if (!$this->getId()) {
$this->setSubscriberConfirmCode($this->randomSequence());
}
$isConfirmNeed = $this->_scopeConfig->getValue(
self::XML_PATH_CONFIRMATION_FLAG, \Magento\Store\Model\ScopeInterface::SCOPE_STORE
) == 1 ? true : false;
$isOwnSubscribes = false;
$isSubscribeOwnEmail = $this->_customerSession->isLoggedIn() && $this->_customerSession->getCustomerDataObject()->getEmail() == $email;
if (!$this->getId() || $this->getStatus() == self::STATUS_UNSUBSCRIBED || $this->getStatus() == self::STATUS_NOT_ACTIVE
) {
if ($isConfirmNeed === true) {
// if user subscribes own login email - confirmation is not needed
$isOwnSubscribes = $isSubscribeOwnEmail;
if ($isOwnSubscribes == true) {
$this->setStatus(self::STATUS_SUBSCRIBED);
} else {
$this->setStatus(self::STATUS_NOT_ACTIVE);
}
} else {
$this->setStatus(self::STATUS_SUBSCRIBED);
}
$this->setSubscriberEmail($_POST['email']);
}
if(!empty($_POST['subscriber_name']) ){
$this->setSubscriberName($_POST['subscriber_name']); //subscriber_name
$this->setSubscriberDateofbirth($_POST['subscriber_dateofbirth']); //date of birth
$this->setSubscriberCountrycode($_POST['subscriber_countrycode']); //country code
}
if ($isSubscribeOwnEmail) {
try {
$customer = $this->customerRepository->getById($this->_customerSession->getCustomerId());
$this->setStoreId($customer->getStoreId());
$this->setCustomerId($customer->getId());
} catch (NoSuchEntityException $e) {
$this->setStoreId($this->_storeManager->getStore()->getId());
$this->setCustomerId(0);
}
} else {
$this->setStoreId($this->_storeManager->getStore()->getId());
$this->setCustomerId(0);
}
$this->setStatusChanged(true);
try {
$this->save();
if ($isConfirmNeed === true && $isOwnSubscribes === false
) {
$this->sendConfirmationRequestEmail();
} else {
$this->sendConfirmationSuccessEmail();
}
return $this->getStatus();
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
Best Answer
in controller