Question

I want to implement custom full text search functionality for front end that fetch result only from company table. Kindly please let me know if you guys have any idea.

In frontend User can search with a keyword it may match with company street address or company name or company city or state. so based on that in frontend need to show companies list.

Thanks!!

Was it helpful?

Solution

Try this one. This may help you surely in some way. Catalog search result page will show the results from the company table only. Fields are based on the b2b company table with OR condition.

Block Files

File - Vendor\Company\Block\Company\ListCompany.php

<?php
namespace Vendor\Company\Block\Company;

use Magento\Company\Model\ResourceModel\Company\CollectionFactory as CompanyCollectionFactory;
use Magento\Directory\Model\ResourceModel\Country\CollectionFactory as CountryCollectionFactory;
use Magento\Directory\Model\ResourceModel\Region\CollectionFactory as RegionCollectionFactory;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Magento\Theme\Block\Html\Pager;
use Magento\Company\Api\Data\CompanyInterface;
use Vendor\Company\Model\Url;



class ListCompany extends Template
{
    /**
     * @var CompanyCollectionFactory
     */
    private $companyCollectionFactory;
    /**
     * @var \Vendor\Company\Model\ResourceModel\Company\Collection
     */
    private $companies;
    /**
     * @var Url
     */
    private $urlModel;

    /**
     * @var \Magento\Framework\App\RequestInterface
     */
    private $httpRequest;

    /**
     * ListCompany constructor.
     * @param Context $context
     * @param CompanyCollectionFactory $companyCollectionFactory
     * @param CountryCollectionFactory $countryCollectionFactory
     * @param Url $urlModel
     * @param array $data
     */
    public function __construct(
        Context $context,
        CompanyCollectionFactory $companyCollectionFactory,
        CountryCollectionFactory $countryCollectionFactory,
        RegionCollectionFactory $regionCollectionFactory,
        \Magento\Directory\Api\CountryInformationAcquirerInterface $countryInformationAcquirer,
        Url $urlModel,
        array $data = []
    )
    {
        $this->companyCollectionFactory = $companyCollectionFactory;
        $this->countryCollectionFactory = $countryCollectionFactory;
        $this->countryInformationAcquirer = $countryInformationAcquirer;
        $this->regionCollectionFactory = $regionCollectionFactory;
        $this->urlModel = $urlModel;
        $this->httpRequest = $context->getRequest();
        parent::__construct($context, $data);
    }


    public function getCompanies()
    {
        if (is_null($this->companies)) {
            $this->companies = $this->companyCollectionFactory->create();
        }
        return $this->companies;
    }



    /**
     * @return $this
     */
    protected function _prepareLayout()
    {
        parent::_prepareLayout();
        /** @var \Magento\Theme\Block\Html\Pager $pager */
        $pager = $this->getLayout()->createBlock(Pager::class, 'vendor.company.company.list.pager');
        $pager->setCollection($this->getCompanies());
        $this->setChild('pager', $pager);
        return $this;
    }

    /**
     * @return string
     */
    public function getPagerHtml()
    {
        return $this->getChildHtml('pager');
    }

    /**
     * @param CompanyInterface $company
     * @return string
     */
    public function getCompanyUrl(CompanyInterface $company)
    {
        return $this->urlModel->getCompanyUrl($company);
    }
}

File - Vendor\Company\Block\Company\ViewCompany.php

<?php
/**
 * MIT
 */


namespace Vendor\Company\Block\Company;

use Magento\Framework\Registry;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

/**
 * @api
 */
class ViewCompany extends Template
{
    /**
     * @var Registry
     */
    private $coreRegistry;
    /**
     * @param Context $context
     * @param Registry $registry
     * @param $imageBuilder
     * @param array $data
     */
    public function __construct(
        Context $context,
        Registry $registry,
        array $data = []
    ) {
        $this->coreRegistry = $registry;
        parent::__construct($context, $data);
    }

    /**
     * get current Company
     *
     * @return \Vendor\Company\Api\Data\CompanyInterface
     */
    public function getCurrentCompany()
    {
        return $this->coreRegistry->registry('current_company');
    }
}

Controller Files

File - Vendor\Company\Controller\Company\Index.php

<?php
namespace Vendor\Company\Controller\Company;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

class Index extends Action
{

    protected $scopeConfig;
    /**
     * @param Context $context
     * @param PageFactory $resultPageFactory
     * @param ScopeConfigInterface $scopeConfig
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        ScopeConfigInterface $scopeConfig
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
        $this->scopeConfig = $scopeConfig;
    }
    /**
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        return $resultPage;
    }
}

File - Vendor\Company\Controller\Company\View.php

<?php
namespace Vendor\Company\Controller\Company;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\Result\Forward;
use Magento\Framework\View\Result\Page;
use Magento\Framework\Registry;
use Magento\Store\Model\ScopeInterface;
use Magento\Company\Api\CompanyRepositoryInterface;
use Vendor\Company\Model\Url as UrlModel;
use Magento\Store\Model\StoreManagerInterface;

class View extends Action
{
    /**
     * @var \Magento\Company\Api\CompanyRepositoryInterface
     */
    protected $companyRepository;

    /**
     * @var \Magento\Framework\Registry
     */
    protected $coreRegistry;
    protected $urlModel;
    private $storeManager;
    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    public function __construct(
        Context $context,
        CompanyRepositoryInterface $companyRepository,
        Registry $coreRegistry,
        UrlModel $urlModel,
        StoreManagerInterface $storeManager,
        ScopeConfigInterface $scopeConfig
    ) {
        $this->companyRepository = $companyRepository;
        $this->coreRegistry = $coreRegistry;
        $this->urlModel = $urlModel;
        $this->storeManager = $storeManager;
        $this->scopeConfig = $scopeConfig;
        parent::__construct($context);
    }

    /**
     * @return \Magento\Framework\Controller\Result\Forward|\Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        try {
            $companyId = (int)$this->getRequest()->getParam('id');
            $company = $this->companyRepository->get($companyId);


            $validStores = [$this->storeManager->getStore()->getId(), 0];
            if (!$company) {
                throw new \Exception();
            }
        } catch (\Exception $e) {
            /** @var Forward $resultForward */
            $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD);
            $resultForward->forward('noroute');
            return $resultForward;
        }

        $this->coreRegistry->register('current_company', $company);
        /** @var Page $resultPage */
        $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);

        $pageMainTitle = $resultPage->getLayout()->getBlock('page.main.title');
        if ($pageMainTitle && $pageMainTitle instanceof \Magento\Theme\Block\Html\Title) {
            $pageMainTitle->setPageTitle($company->getCompanyName());
        }
        return $resultPage;
    }
}

etc files

File - Vendor/Company/etc/frontend/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="vendor_company" frontName="catalogcompany">
            <module name="Vendor_Company" />
        </route>
    </router>
</config>

File - Vendor/Company/etc/module.xml

<?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="Vendor_Company">
        <sequence>
            <module name="Magento_Directory"/>
            <module name="Magento_Company"/>
        </sequence>
    </module>
</config>

Model File

File - Vendor/Company/Model/Url.php

<?php
namespace Vendor\Company\Model;

use Magento\Framework\UrlInterface;
use Magento\Company\Api\Data\CompanyInterface;

class Url
{
    protected $urlBuilder;
    public function __construct(
        UrlInterface $urlBuilder
    ) {
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * @return string
     */
    public function getListUrl()
    {
        return $this->urlBuilder->getUrl('vendor_company/company/index/');
    }

    /**
     * @param CompanyInterface $company
     * @return string
     */
    public function getCompanyUrl(CompanyInterface $company)
    {
        return $this->urlBuilder->getUrl('vendor_company/company/view', ['id' => $company->getId()]);
    }
}

Layout Files

Vendor/Company/view/frontend/layout/catalogsearch_result_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="search.result" remove="true" />

        <referenceContainer name="content">
            <block class="Vendor\Company\Block\Company\SearchCompany" template="Vendor_Company::company/list.phtml" name="vendor.company.company.searchlist" />

            <container name="vendor_landing_placeholder" htmlTag="div" htmlClass="companyLandingSearchPage">
                <block name="vendor_landing_placeholder_render_me" class="Magento\Framework\View\Element\Text">
                    <arguments>
                        <argument name="text" xsi:type="string"><![CDATA[&nbsp;]]></argument>
                    </arguments>
                </block>
            </container>
        </referenceContainer>
    </body>
</page>

Vendor/Company/view/frontend/layout/vendor_company_company_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="content">
            <block class="Vendor\Company\Block\Company\ListCompany" name="vendor.company.company.list"
                   template="Vendor_Company::company/list.phtml"/>
        </referenceBlock>
    </body>
</page>

Vendor/Company/view/frontend/layout/vendor_company_company_view.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
    <referenceBlock name="content">
        <block class="Vendor\Company\Block\Company\ViewCompany" name="vendor.company.company.view" template="Vendor_Company::company/view.phtml" />
    </referenceBlock>
    </body>
</page>

Templates Files

Vendor/Company/view/frontend/templates/company/list.phtml

<?php
/** @var \Vendor\Company\Block\Company\ListCompany $block */
?>
<style>
    .company-item {
        float: left;
        width: 45%;
        margin: 10px;
        height: 120px;
    }
.company-toolbar.toolbar.bottom{clear:both}
</style>
<?php $companies = $block->getCompanies();?>
<?php if ($companies->getSize()) : ?>
<div class="company-toolbar toolbar top"><?php echo $block->getPagerHtml(); ?></div>
<div class="company-list">
    <?php foreach ($companies as $company) : ?>
        <div class="company-item">
            <?php if ($name = $company->getCompanyName()) :?>
            <div class="company-name">
                <strong><?= $block->escapeHtml(__('Company Name')) ?></strong>:
                <?= $block->escapeHtml($name);?>
            </div>
            <?php endif;?>

            <?php if ($name = $company->getLegalName()) :?>
                <div class="company-name">
                    <strong><?= $block->escapeHtml(__('Legal Name')) ?></strong>:
                    <?= $block->escapeHtml($name);?>
                </div>
            <?php endif;?>

            <?php if ($city = $company->getCity()) :?>
            <div class="company-city">
                <strong><?= $block->escapeHtml(__('City')) ?></strong>:
                <?= $block->escapeHtml($city);?>
            </div>
            <?php endif;?>

            <?php if ($countryID = $company->getCountryId()) :?>
                <div class="company-country">
                    <strong><?= $block->escapeHtml(__('CountryID')) ?></strong>:
                    <?= $block->escapeHtml($countryID);?>
                </div>
            <?php endif;?>
            <?php if ($regionid = $company->getRegionId()) :?>
                <div class="company-region">
                    <strong><?= $block->escapeHtml(__('Regionid')) ?></strong>:
                    <?= $block->escapeHtml($regionid);?>
                </div>
            <?php endif;?>

            <div class="company-company-code">
                <a href="<?= $block->escapeUrl($block->getCompanyUrl($company));?>">
                    View <?= $block->escapeHtml($company->getCompanyName());?>
                </a>
            </div>
        </div>
    <?php endforeach; ?>
    <div class="company-toolbar toolbar bottom"><?php echo $block->getPagerHtml(); ?></div>
<?php else : ?>
    <?= $block->escapeHtml(__('There are no Companies at this moment')); ?>
<?php endif;?>

Vendor/Company/view/frontend/templates/company/view.phtml

<?php
/** @var \Vendor\Company\Block\Company\ViewCompany $block */
?>
<?php $company = $block->getCurrentCompany();?>
<div class="company-view">
    <div class="company-company-name">
        <strong><?= $block->escapeHtml(__('Company Name')) ?></strong>:
        <?= $block->escapeHtml($company->getCompanyName());?>
    </div>
    <?php if ($legal = $company->getLegalName()) :?>
    <div class="company-name">
        <strong><?= $block->escapeHtml(__('Legal Name')) ?></strong>:
        <?= $block->escapeHtml($legal);?>
    </div>
    <?php endif;?>

    <?php if ($city = $company->getCity()) :?>
    <div class="company-city">
        <strong><?= $block->escapeHtml(__('City')) ?></strong>:
        <?= $block->escapeHtml($city);?>
    </div>
    <?php endif;?>

</div>

Pages will look this

  1. Search Results page - http://www.domain.com/catalogsearch/result/?q=com
  2. Company view page - http://www.domain.com/catalogcompany/company/view/id/2/
  3. Company index page - http://www.domain.com/catalogcompany/company/index

Updated File - Vendor\Company\Block\Company\SearchCompany.php

<?php
namespace Vendor\Company\Block\Company;

use Magento\Company\Api\Data\CompanyInterface;
use Magento\Company\Model\ResourceModel\Company\CollectionFactory as CompanyCollectionFactory;
use Magento\Directory\Api\CountryInformationAcquirerInterface;
use Magento\Directory\Model\ResourceModel\Country\CollectionFactory as CountryCollectionFactory;
use Magento\Directory\Model\ResourceModel\Region\CollectionFactory as RegionCollectionFactory;
use Magento\Framework\App\ResourceConnection as MagentoResource;
use Magento\Framework\DB\Helper\Mysql\Fulltext as MySQLFullText;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Magento\Theme\Block\Html\Pager;
use Vendor\Company\Model\Url;

class SearchCompany extends Template
{
    private $companyCollectionFactory;
    private $companies;
    private $urlModel;
    private $httpRequest;
    private $connection;

    public function __construct(
        Context $context,
        CompanyCollectionFactory $companyCollectionFactory,
        CountryCollectionFactory $countryCollectionFactory,
        RegionCollectionFactory $regionCollectionFactory,
        CountryInformationAcquirerInterface $countryInformationAcquirer,
        MagentoResource $resource,
        MySQLFullText $fulltext,
        Url $urlModel,
        array $data = []
    )
    {
        $this->companyCollectionFactory = $companyCollectionFactory;
        $this->countryCollectionFactory = $countryCollectionFactory;
        $this->countryInformationAcquirer = $countryInformationAcquirer;
        $this->regionCollectionFactory = $regionCollectionFactory;
        $this->urlModel = $urlModel;
        $this->httpRequest = $context->getRequest();
        $this->query = $this->httpRequest->getParam('q');
        $this->resource = $resource;
        $this->fullTextSelect = $fulltext;
        parent::__construct($context, $data);
    }


    protected function getConnection()
    {
        if (!$this->connection) {
            $this->connection = $this->resource->getConnection('core_write');
        }
        return $this->connection;
    }

    private function escapePhrase(string $phrase)
    {
        return preg_replace('/@+|[@+-]+$|[<>]/', '', $phrase);
    }

    public function prepareFullTextQuery($term)
    {
        $term = $this->fullTextSelect->removeSpecialCharacters($term);
        $matchQuery = $this->fullTextSelect->getMatchQuery(
            ['company_name' => 'company_name', 'legal_name' => 'legal_name'],
            $this->escapePhrase($term),
            MySQLFullText::FULLTEXT_MODE_NATURAL_QUERY
        );
        return $matchQuery;
    }


    public function getCompanies()
    {
        if (empty($this->httpRequest->getParam('q'))) {
            return $this->companies;
        }
        $this->query = $query = $this->httpRequest->getParam('q');

        $this->companies = $this->companyCollectionFactory->create();
        $this->companies->getSelect()->where($this->prepareFullTextQuery($query));
        //echo $this->companies->getSelect()->__toString();
        if ($this->companies->getSize()) {
            return $this->companies;
        }

        $countries = $this->countryInformationAcquirer->getCountriesInfo();
        $countriesNames = array();
        foreach ($countries as $key => $row) {
            $countriesNames[$key]['code'] = $row->getTwoLetterAbbreviation();
            $countriesNames[$key]['name'] = $row->getFullNameEnglish();
        }
        $results = $this->array_search_partial($countriesNames, $query);

        //Regions
        $this->regions = $this->regionCollectionFactory->create();
        $this->regions->addFieldToSelect('region_id')
            ->addFieldToFilter(
                array('name'),
                array(array('like' => '%' . $query . '%'))
            );
        $regionIDs = array();
        foreach ($this->regions as $id) {
            $regionIDs[] = $id->getRegionId();
        }
        //echo $this->countries->getSelect()->__toString();

        //If still not companies found then fallback
        if ($this->companies) {
            $this->companies = $this->companyCollectionFactory->create()
                ->addFieldToFilter(
                    array('company_name', 'legal_name', 'city', 'street', 'country_id', 'region_id'),
                    array(
                        array('like' => '%' . $query . '%'), array('like' => '%' . $query . '%'),
                        array('like' => '%' . $query . '%'), array('like' => '%' . $query . '%'),
                        array('in' => $results), array('in' => $regionIDs)
                    )
                );

            //echo $this->companies->getSelect()->__toString(); die;
            //->addFieldToFilter('is_active', CompanyInterface::STATUS_ENABLED)
            //->setOrder('company_name', 'ASC');
        }
        return $this->companies;
    }

    private function array_search_partial($array, $keyword)
    {
        $results = array();
        foreach ($array as $value) {
            if (strpos(strtolower($value['name']), strtolower($keyword)) !== false) {
                $results[] = $value['code'];
            }
        }
        return $results;
    }

    protected function _prepareLayout()
    {
        $title = $this->getSearchQueryText();
        $this->pageConfig->getTitle()->set($title);
        $breadcrumbs = $this->getLayout()->getBlock('breadcrumbs');
        if ($breadcrumbs) {
            $breadcrumbs->addCrumb(
                'home', [ 'label' => __('Home'), 'title' => __('Go to Home Page'), 'link' => $this->_storeManager->getStore()->getBaseUrl()
                ]
            )->addCrumb( 'search', ['label' => $title, 'title' => $title] );
        }

        parent::_prepareLayout();
        $pager = $this->getLayout()->createBlock(Pager::class, 'vendor.company.company.list.pager');

        $pager->setCollection($this->getCompanies());
        $this->setChild('pager', $pager);
        return $this;
    }

    public function getSearchQueryText()
    {
        return __("Company results for: '%1'", $this->query);
    }

    public function getPagerHtml()
    {
        return $this->getChildHtml('pager');
    }

    public function getCompanyUrl(CompanyInterface $company)
    {
        return $this->urlModel->getCompanyUrl($company);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top