5

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!!

6
  • Please check this post if it helps! magento.stackexchange.com/questions/131224/… Jul 17, 2020 at 11:44
  • please explain which type of search you need.
    – Msquare
    Aug 6, 2020 at 5:04
  • please provide us a real example of what you need. Aug 6, 2020 at 13:20
  • @DaniloEmpire added real example. basically magento b2b company should be searchable in the frontend.
    – sivakumar
    Aug 7, 2020 at 4:03
  • company table is your custom table? and have you created the model for that one as well, right? Aug 7, 2020 at 6:29

1 Answer 1

1

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);
    }
}
6
  • this is not fulltext search. this is search with like
    – sivakumar
    Aug 12, 2020 at 4:25
  • in that case some changes are require.. will post in some time.
    – sandip
    Aug 12, 2020 at 5:20
  • is there a way to add elastic search?
    – sivakumar
    Aug 12, 2020 at 5:30
  • yes it can be added but fulltext only better works with mysql.
    – sandip
    Aug 12, 2020 at 5:34
  • @sivakumar Use this Updated File - Vendor\Company\Block\Company\SearchCompany.php - run deployment commands if needed.
    – sandip
    Aug 12, 2020 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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