2

I have a store collection. And it has the following fields

 [0] => Array
    (
        [location_id] => 5
        [title] => Los Angeles
        [description] => 
        [status] => 1
        [sort_order] => 0
        [country_id] => US
        [region_id] => 1
        [city] => Los Angeles
        [street] => 1605 W. Olympic Blvd. 
        [zip] => 90015
        [phone] => (213)639-2100
        [zoom] => 16
        [latitude] => 34.0497
        [longitude] => -118.275
        [image] => location/d/o/download_1_.jpeg
        [custom_marker] => location/d/o/download_1.png
        [store_location_code] => 1
        [store_manager] => Mike
        [store_email] => la@icuracao.com
        [fax] => (213)639-2196
        [distance] => 37.97125176816877
    )

distance is not a column in db how to sort the store collection in the ascending order of distance app/code/Aheadworks/StoreLocator/Model/Location.php

<?php
/**
  * Copyright 2018 aheadWorks. All rights reserved.
  * See LICENSE.txt for license details.
  */

  namespace Aheadworks\StoreLocator\Model;

 use Aheadworks\StoreLocator\Api\Data\LocationInterface;
  use Aheadworks\StoreLocator\Api\Data\LocationInterfaceFactory;
 use Aheadworks\StoreLocator\Model\ResourceModel\Location as ResourceModelLocation;
 use Magento\Framework\Api\DataObjectHelper;
 use Magento\Framework\Data\Collection\AbstractDb;
 use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\Context;
 use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
 use Magento\Framework\Registry;
  use Magento\Store\Model\StoreManagerInterface;

  /**
 * Class Location.
 */
 class Location extends AbstractModel
 {
/**
 * @var string
 */
protected $_eventPrefix = 'location';

/**
 * @var string
 */
protected $_eventObject = 'location';

/**
 * @var array
 */
protected static $searchFields = ['country_id', 'region_id', 'city', 'zip'];

/**
 * @var StoreManagerInterface
 */
protected $storeManager;

/**
 * @var LocationInterfaceFactory
 */
protected $locationDataFactory;

/**
 * @var DataObjectHelper
 */
protected $dataObjectHelper;

/**
 * @param Context $context
 * @param Registry $registry
 * @param StoreManagerInterface $storeManager
 * @param ResourceModelLocation $resource
 * @param LocationInterfaceFactory $locationDataFactory
 * @param DataObjectHelper $dataObjectHelper
 * @param AbstractDb $resourceCollection
 * @param array $data
 */
public function __construct(
    Context $context,
    Registry $registry,
    StoreManagerInterface $storeManager,
    ResourceModelLocation $resource,
    LocationInterfaceFactory $locationDataFactory,
    DataObjectHelper $dataObjectHelper,
    AbstractDb $resourceCollection = null,
    array $data = []
) {
    $this->storeManager = $storeManager;
    $this->locationDataFactory = $locationDataFactory;
    $this->dataObjectHelper = $dataObjectHelper;
    parent::__construct(
        $context,
        $registry,
        $resource,
        $resourceCollection,
        $data
    );
}

/**
 * {@inheritdoc}
 */
public function _construct()
{
    $this->_init(ResourceModelLocation::class);
}

/**
 * @return LocationInterface
 */
public function getDataModel()
{
    $locationData = $this->getData();
    $locationDataObject = $this->locationDataFactory->create();

    $this->dataObjectHelper->populateWithArray(
        $locationDataObject,
        $locationData,
        LocationInterface::class
    );

    return $locationDataObject;
}

/**
 * Retrieve location collection model populated with data.
 *
 * @param array $filters
 * @return AbstractCollection
 */
public function getLocationCollectionBySearch(array $filters = [])
{
    $collection = $this->getCollection();

    if (isset($filters['radius']) && isset($filters['measurement'])) {
        $collection->addRadiusFilter(
            $filters['radius'],
            $filters['measurement'],
            $filters['latitude'],
            $filters['longitude']

        );
    }

    foreach ($filters as $filter => $value) {
        if ($value && in_array($filter, self::$searchFields)) {
            $collection->addFieldToFilter($filter, $value);
        }
    }

    $collection->addStoreFilter($this->storeManager->getStore()->getId());

    $collection->addFieldToFilter('status', 1);
    // if (!empty($filters) && (!empty($filters['street']))) {
    //   $collection->addOrder("distance","ASC");
    // }
    $collection = $collection->load();



    return $collection;
}
}

app/code/Aheadworks/StoreLocator/Controller/Index/Index.php

  namespace Aheadworks\StoreLocator\Controller\Index;

 use Aheadworks\StoreLocator\Helper\Config;
 use Aheadworks\StoreLocator\Model\Location;
 use Magento\Framework\App\Action\Action;
 use Magento\Framework\App\Action\Context;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\View\Result\Page;
 use Magento\Framework\View\Result\PageFactory;

/**
  * Class Index.
  */
class Index extends Action
 {
/**
 * @var PageFactory
 */
protected $resultPageFactory;

/**
 * @var Location
 */
protected $locationModel;

/**
 * @var Config
 */
protected $helperConfig;

/**
 * @param Context $context
 * @param PageFactory $resultPageFactory
 * @param Location $locationModel
 * @param Config $helperConfig
 */
public function __construct(
    Context $context,
    PageFactory $resultPageFactory,
    Location $locationModel,
    Config $helperConfig
) {
    $this->resultPageFactory = $resultPageFactory;
    $this->locationModel = $locationModel;
    $this->helperConfig = $helperConfig;
    parent::__construct($context);
}

/**
 * Default page
 *
 * @return Page
 * @throws LocalizedException
 */
public function execute()
{
    $postData = $this->getRequest()->getPostValue();
    $searchPostData = [];
    if ($postData) {
        $searchPostData = $postData['search'];
    }

    /** @var \Magento\Framework\View\Result\Page $resultPage */
    $resultPage = $this->resultPageFactory->create();
    $resultPage->getLayout()->initMessages();
    $resultPage->getConfig()->getTitle()->set($this->helperConfig->getTitle());

    if (isset($searchPostData)) {
        $resultPage->getLayout()->getBlock('aw_store_locator_search')->setData($searchPostData);
    }

    $collection = $this->locationModel->getLocationCollectionBySearch($searchPostData);
    $collection = $this->sortCollection($collection, function($a, $b) {
      return (int)($a->getDistance() >= $b->getDistance());
    });
    echo "<pre>";
    print_r($collection->getData());die;
    foreach($collection as $store)
    {
      $sorter[]=$store->getDistance();
    }
    // echo "<pre>";
    // print_r($sorter);
    // exit();
    $locationBlock = $resultPage->getLayout()->getBlock('aw_store_locator_location');
    if ($locationBlock) {
        $locationBlock->setCollection($collection);
    }

    $mapBlock = $resultPage->getLayout()->getBlock('aw_store_locator_map');
    // echo "<pre>";
    // print_r(getLayout()->getBlock('aw_store_locator_map'));
    // exit();
    if ($mapBlock) {
                $mapBlock->setCollection($collection);
    }

    return $resultPage;
}



protected function sortCollection($collection, callable $sorter) {
    $collectionReflection = new \ReflectionObject($collection);
    $itemsPropertyReflection = $collectionReflection->getItems();
    $itemsPropertyReflection->setAccessible(true); // Make it accessible

    $collectionItems = $itemsPropertyReflection->getValue($collection);

    usort($collectionItems, $sorter);

    $itemsPropertyReflection->setValue($collection, $collectionItems);

    $itemsPropertyReflection->setAccessible(false); // Return restriction back

    return $collection;
}

}
  • 1
    Is sorting after loading a best practice? – Nismath vi Oct 23 '18 at 10:32
0

Use setOrder for sorting

$collection->setOrder('distance','ASC');

you can also use addAttributeToSort() by default it's ASC

$collection->addAttributeToSort('distance');

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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