Question

First my thanks for reading my question. I learning to program in M2 so forgive me potential strange questions. So far I managed to create a custom module and an edit page. My main database table is names dsssolutions_management_vendor. My form loads this as expected, but now I want to load additional tables to also populate my form. For this I would like to follow coding standards as good as possible.

From this point I'm not sure and can't find online what the correct approach is to load by default additional database tables into my form and later maybe also easily save this data correctly, but lets start with the join to figure out correctly. For the form I use ui_component.

Personally I would expect that in some way I must alter the Vendor/DataProvider so that the getData() function will load the data by default. Below my current code for this file. Notice that I altered the get id with ['general'] because I do use tabs, without M2 wont populate the edit form.

<?php declare(strict_types=1);


namespace DssSolutions\Management\Model\Vendor;

use DssSolutions\Management\Model\ResourceModel\Vendor\CollectionFactory;
use Magento\Framework\App\Request\DataPersistorInterface;


class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{

protected $dataPersistor;

protected $collection;

protected $loadedData;

/**
 * Constructor
 *
 * @param string $name
 * @param string $primaryFieldName
 * @param string $requestFieldName
 * @param CollectionFactory $collectionFactory
 * @param DataPersistorInterface $dataPersistor
 * @param array $meta
 * @param array $data
 */
public function __construct(
    $name,
    $primaryFieldName,
    $requestFieldName,
    CollectionFactory $collectionFactory,
    DataPersistorInterface $dataPersistor,
    array $meta = [],
    array $data = []
) {
    $this->collection = $collectionFactory->create();
    $this->dataPersistor = $dataPersistor;
    parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
}

/**
 * Get data
 *
 * @return array
 */
public function getData()
{
    if (isset($this->loadedData)) {
        return $this->loadedData;
    }
    $items = $this->collection->getItems();
    foreach ($items as $model) {
        $this->loadedData[$model->getId()]['general'] = $model->getData();
    }
    $data = $this->dataPersistor->get('dsssolutions_management_vendor');

    if (!empty($data)) {
        $model = $this->collection->getNewEmptyItem();
        $model->setData($data);
        $this->loadedData[$model->getId()] = $model->getData();
        $this->dataPersistor->clear('dsssolutions_management_vendor');
    }

    return $this->loadedData;
}
}

The database that I want to join is named dsssolutions_management_vendoraddress (I know potentially naming convention should be vendoraddresses but can change this later). In this table I have a column vendor_id that should match with the id from the vendor record I retreive. For now one-to-one but later maybe one-to-many.

An potential other location to achieve this would maybe be the Vendor/edit.php. To be sure also this code below.

<?php declare(strict_types=1);


namespace DssSolutions\Management\Controller\Adminhtml\Vendor;


class Edit extends \DssSolutions\Management\Controller\Adminhtml\Vendor
{

protected $resultPageFactory;

/**
 * @param \Magento\Backend\App\Action\Context $context
 * @param \Magento\Framework\Registry $coreRegistry
 * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
 */
public function __construct(
    \Magento\Backend\App\Action\Context $context,
    \Magento\Framework\Registry $coreRegistry,
    \Magento\Framework\View\Result\PageFactory $resultPageFactory
) {
    $this->resultPageFactory = $resultPageFactory;
    parent::__construct($context, $coreRegistry);
}

/**
 * Edit action
 *
 * @return \Magento\Framework\Controller\ResultInterface
 */
public function execute()
{
    // 1. Get ID and create model
    $id = $this->getRequest()->getParam('vendor_id');
    $model = $this->_objectManager->create(\DssSolutions\Management\Model\Vendor::class);

    // 2. Initial checking
    if ($id) {
        $model->load($id);
        if (!$model->getId()) {
            $this->messageManager->addErrorMessage(__('This Vendor no longer exists.'));
            /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
            $resultRedirect = $this->resultRedirectFactory->create();
            return $resultRedirect->setPath('*/*/');
        }
    }
    $this->_coreRegistry->register('dsssolutions_management_vendor', $model);

    // 3. Build edit form
    /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
    $resultPage = $this->resultPageFactory->create();
    $this->initPage($resultPage)->addBreadcrumb(
        $id ? __('Edit Vendor') : __('New Vendor'),
        $id ? __('Edit Vendor') : __('New Vendor')
    );
    $resultPage->getConfig()->getTitle()->prepend(__('Vendors'));
    $resultPage->getConfig()->getTitle()->prepend($model->getId() ? __('Edit Vendor %1', $model->getVendorName()) : __('New Vendor'));
    return $resultPage;
}
}

Hopefully someone can point me here in the correct direction.

EDIT After testing I have added the following code to Model/Vendor/Collection

protected function _afterLoad()
{
    $select= $this->getSelect();
    $select->joinLeft(
        array('SecondTable'=>$this->getTable('dsssolutions_management_vendoraddress')),
        'main_table.vendor_id=SecondTable.vendor_id',
        array('*')
    );

    echo 'Afterload function<br/>';
    echo $select;
    echo '<br/>';
    return parent::_afterLoad();
}

The echo from $select now gives me the following SQL Query

SELECT `main_table`.*, `SecondTable`.* FROM `dsssolutions_management_vendor` AS `main_table` LEFT JOIN `dsssolutions_management_vendoraddress` AS `SecondTable` ON main_table.vendor_id=SecondTable.vendor_id WHERE (`vendor_id` = '1')

So this seems to be correct, but when I now do a die(print_r($this->loadedData)); in my DataProvider I can see that I still only the main table is coming back. If I past the SQL Query into phpmyadmin I get an warning that the vendor_id column is ambiguous.

So a little closer it seems. Hopefully somebody can help me further here.

Était-ce utile?

La solution

After a lot of trial and error I found out that the following will create the expected behavior

  • The database column for the vendor table should be different in naming convention as the join table, so I changed this to id instead of vendor_id
  • The joined table in this case 'dsssolutions_management_vendoraddress' must have an FK relationship with the table vendor

The follwing coding had to be adjusted:

In Vendor/Collection.php added the code

protected function _initSelect()
{
    $this->getSelect()
        ->from(['main_table' => $this->getMainTable()])
        ->join('dsssolutions_management_vendoraddress',
            'main_table.id = dsssolutions_management_vendoraddress.vendor_id',
            [
                'vendoraddress_id',
                'vendor_addres_type',
                'vendor_street',
                'vendor_zipcode',
                'vendor_country',
                'vendor_attention'
            ]);
    return $this;
}

In the file ResourceModel/Vendor.php added the following coding

protected function _getLoadSelect($field, $value, $object)
{
    $field = $this->getConnection()->quoteIdentifier(sprintf('%s.%s', $this->getMainTable(), $field));
    $select = $this->getConnection()
        ->select()
        ->from($this->getMainTable())
        ->where($field . '=?', $value)
        ->join('dsssolutions_management_vendoraddress',
            'dsssolutions_management_vendor.id = dsssolutions_management_vendoraddress.vendor_id',
            [
                'vendoraddress_id',
                'vendor_addres_type',
                'vendor_street',
                'vendor_zipcode',
                'vendor_country',
                'vendor_attention'
            ]);
    return $select;
}

With these changes Magento loads the join by default when you retreive data. Hopefully this solution will become handy for someone else.

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top