Api Pagination in Symfony - php

I am working on API, I have a controller that query for results to a framework7 app. (first, last and both). I, however, want to add pagination from API to framework but I have not paginated in Symfony before, what is the best practice?
I tried paginator but there are not many examples of it. Below is my controller function.
public function getEventSessionAttendeeAction(request $request, $eventSessionId)
{
$searchFields = [
'o.email',
'a.email',
'a.firstName',
'a.lastName',
'a.barcode1',
'a.barcode2',
'a.id',
'o.id'
];
/** #var \KCM\ApiBundle\Entity\Api\EventSession $eventSession */
$eventSession = $this->get('doctrine')->getRepository('KCMApiBundle:EventSession')->findOneBy(
[
'id' => $eventSessionId
]
);
/** #var ApiEntity\Event $event */
$event = $eventSession->getEvent();
$childSafe = $event->getChildSafe();
$filter = $request->get('filter');
$match_level = 0;
//Searches by email address
if ( filter_var($filter, FILTER_VALIDATE_EMAIL)) {
$searchFields = [
'a.email'
];
$match_level = 1;
//Searches for first or last name
}elseif(preg_match('/^[a-zA-Z\-]*$/', $filter)){
$searchFields = [
'a.lastName',
'a.firstName'
];
$match_level = 2;
//Searches by barcode
}elseif (preg_match('/^[0-9]+/', $filter)){
if ($childSafe == 2) {
$searchFields = [
'a.barcode3'
];
} else {
$searchFields = [
'a.barcode1'
];
}
$match_level = 4;
}
//Searches for first and last name(must have at least first characters for each
if(preg_match('/^([a-z|A-Z]+)\s{1}([a-z|A-Z]+)/', $filter)){
$match_level = 3;
}elseif (preg_match('/^\s*$/', $filter)){
$match_level = 5;
}
try {
/** #var ApiEntity\EventSession $eventSession */
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->select(array('a', 'o'))
->from('KCMApiBundle:EventAttendee', 'a')
->join('a.eventOrder', 'o')
->join('o.event', 'e')
->join('e.eventSessions', 'es')
->where($qb->expr()->andX(
$qb->expr()->eq('es.id', $qb->expr()->literal($eventSessionId))
))
->andWhere('a.sessionCheckedIn = 1');
if ($match_level === 3){
$expr = $qb->expr()->andX();
list($first, $last) = explode(' ', $filter);
$last = $last. '%';
$expr->add($qb->expr()->like('a.lastName', $qb->expr()->literal($last)));
$first = $first. '%';
$expr->add($qb->expr()->like('a.firstName',$qb->expr()->literal($first)));
}elseif ($match_level === 5){
$expr = $qb->expr()->andX();
$paginator = new Paginator($qb);
$paginator->getQuery()
->setFirstResult(0)
->setMaxResults(10);
}else {
$expr = $qb->expr()->orX();
foreach ($searchFields as $field) {
if ($match_level === 1) {
$literalFilter = $filter;
$expr->add($qb->expr()->like($field, $qb->expr()->literal($literalFilter)));
} elseif ($match_level === 2) {
$literalFilter = $filter;
$expr->add($qb->expr()->like($field, $qb->expr()->literal($literalFilter)));
} elseif ($match_level === 4) {
$literalFilter = $filter;
$expr->add($qb->expr()->eq($field, $qb->expr()->literal($literalFilter)));
}
}
}
$qb->andWhere($expr);
$results = $qb->getQuery()->getResult();
if ($results) {
return $this->getApi()->serialize($results);
}
return new Response(null, Response::HTTP_NOT_FOUND);
} catch (\Exception $e) {
$this->get('logger')->error($e->getMessage());
}
}
What I am trying to eventually do is to be able to use this query to paginate to the framework7 app. should I create a new public function to paginate or is there a way to do it within this function?

Did you try to use knppagination bundle?
https://github.com/KnpLabs/KnpPaginatorBundle

Related

filtering and sorting with pagination in laravel

Hi I'm using Laravel and I have a sorting and filtering system it works via url like this
http://localhost:8000/halehule/category/103?type=all&minprice=+10+&maxprice=+10000000000+&color=&sortBy%5Bfield%5D=price&sortBy%5BorderBy%5D=desc
so when I use pagination it does not work and refresh to original page like this :
http://localhost:8000/halehule/category/103?page=2
How can I use pagination with sorting and filtering like this
here is my method
public function brandProduct($shop, $id, Request $request) {
$colors = Color::all();
$shop = Shop::where('english_name', $shop)->first();
$shopTags = $shop->tags;
$shopCategories = $shop->ProductCategories()->get();
$categories = Shop::where('english_name', $shop->english_name)->first()->ProductCategories()->get()->where('parent_id', null);
$brand = Brand::where('id', $id)->get()->first();
$brands = $shop->brands;
$shopProducts = $shop->products;
$minPriceProduct = $shopProducts->min('price');
$maxPriceProduct = $shopProducts->max('price');
//color product and category product merging
if($request->color == null){
$colorAndBrandProducts = $brand->products->sortByDesc('created_at');
}
else{
$colorProducts = Color::where('code', $request->color)->get()->first()->products;
$brandProducts = $brand->products;
$colorAndBrandProducts = collect();
foreach($colorProducts->toBase()->merge($brandProducts)->groupBy('id') as $allProducts){
if($allProducts->count() > 1){
$colorAndBrandProducts[] = $allProducts;
}
}
$colorAndBrandProducts = $colorAndBrandProducts->first();
}
if ($request->has('type') and $request->has('sortBy') and $request->has('minprice') and $request->has('maxprice') and $request->has('color')) {
if($colorAndBrandProducts != null){
$minPrice = $request->minprice;
$maxPrice = $request->maxprice;
$filterBy = $request->type;
$sortBy = $request->sortBy['field'];
$perPage = 16;
if($shop->template->folderName == 2){
$sortBy_array = explode('|', $request->sortBy['field']);
$sortBy = $sortBy_array[0];
$orderBy = $sortBy_array[1];
}
else{
$orderBy = $request->sortBy['orderBy'];
}
if ($request->type == 'all') {
if ($orderBy == 'desc') {
$products = $colorAndBrandProducts->whereBetween('price', [$minPrice, $maxPrice])->sortByDesc($sortBy)->unique('id');
} else {
$products = $colorAndBrandProducts->whereBetween('price', [$minPrice, $maxPrice])->sortBy($sortBy)->unique('id');
}
} else {
if ($orderBy == 'desc') {
$products = $colorAndBrandProducts->where('type', $filterBy)->whereBetween('price', [$minPrice, $maxPrice])->sortByDesc($sortBy)->unique('id');
} else {
$products = $colorAndBrandProducts->where('type', $filterBy)->whereBetween('price', [$minPrice, $maxPrice])->sortBy($sortBy)->unique('id');
}
}
}
else{
$products = collect();
}
}
else {
$products = $colorAndBrandProducts;
}
$total = $products->count();
$perPage = 16; // How many items do you want to display.
$currentPage = request()->page; // The index page.
$productsPaginate = new LengthAwarePaginator($products->forPage($currentPage, $perPage), $total, $perPage, $currentPage);
$template_folderName = $shop->template->folderName;
SEOTools::setTitle($shop->name . ' | ' . $brand->name);
SEOTools::setDescription($shop->description);
SEOTools::opengraph()->addProperty('type', 'website');
return view("app.shop.$template_folderName.layouts.partials.products", compact('products','minPriceProduct', 'maxPriceProduct', 'shopCategories', 'brand', 'shop', 'categories', 'productsPaginate', 'brands', 'shopTags','colors'));
}
I use this method for sorting and filtering and use pagination works great but without sorting and filtering
just apply ->append($_GET) to your pagination

Creating a new collection from another collection

im creating a collection of specific data from a query that i made, but i need to create a new collection with only some data with custom names properties, i was using arrays, but i need to make it in collections since is easyer to format the data and access some collections methods.
My current code is like:
$activity = [];
$temp = [];
$calculations = collect($user->calculations()
->withTrashed()
->orderBy('updated_at', 'desc')
->get());
foreach($calculations as $calculation){
$temp['type'] = "calculation";
$temp['name'] = $calculation->name;
$user = $this->getUserById($calculation->pivot->user_id);
$temp['user'] = $user->name ." ".$user->surname;
if($calculation->created_at == $calculation->updated_at && $calculation->deleted_at == null)
{
$temp['operation'] = "saved";
$temp['date'] = $calculation->created_at;
$temp['diff'] = Carbon::parse($calculation->created_at)->diffForHumans();
}elseif($calculation->created_at != $calculation->updated_at && $calculation->deleted_at != null)
{
$temp['operation'] = "changed";
$temp['date'] = $calculation->updated_at;
$temp['diff'] = Carbon::parse($calculation->updated_at)->diffForHumans();
}else{
$temp['operation'] = "delete";
$temp['date'] = $calculation->deleted_at;
$temp['diff'] = Carbon::parse($calculation->deleted_at)->diffForHumans();
}
array_push($activity,$temp);
}
$conditions = collect($user->conditions()
->withTrashed()
->orderBy('updated_at', 'desc')
->get());
foreach($conditions as $condition){
$temp['type'] = "condition";
$temp['name'] = $condition->name;
$user = $this->getUserById($condition->user_id);
$temp['user'] = $user->name ." ".$user->surname;
if($condition->created_at == $condition->updated_at && $condition->deleted_at == null)
{
$temp['operation'] = "saved";
$temp['date'] = $condition->created_at;
$temp['diff'] = Carbon::parse($condition->created_at)->diffForHumans();
}elseif($condition->created_at != $condition->updated_at && $condition->deleted_at != null)
{
$temp['operation'] = "alterado";
$temp['date'] = $condition->updated_at;
$temp['diff'] = Carbon::parse($condition->updated_at)->diffForHumans();
}else{
$temp['operation'] = "delete it";
$temp['date'] = $condition->deleted_at;
$temp['diff'] = Carbon::parse($condition->deleted_at)->diffForHumans();
}
array_push($activity,$temp);
I already convert the eloquent query to "collect", but how i cant createa new collections, i need to instead using the array methods, i should use the collection methods to create them.
Basically my main reason is that i need to merge the "conditions" and "calculations" for than be able to order the dataTime the collections.
How about something like this.
I've used transform method on collections (in order to transform the key names). I've replicated your logic and then merged both collections.
$calculations = $user->calculations()
->withTrashed()
->orderBy('updated_at', 'desc')
->get();
$transformed = $calculations->transform(function($item, $key) use($user) {
$toReturn = [];
$toReturn['type'] = "calculation";
$toReturn['name'] = $item->name;
$toReturn['user'] = $user->name;
if($item->created_at == $item->updated_at && $item->deleted_at == null) {
$toReturn['operation'] = "saved";
$toReturn['date'] = $item->created_at;
$toReturn['diff'] = Carbon::parse($item->created_at)->diffForHumans();
} elseif($item->created_at != $item->updated_at && $item->deleted_at != null){
$toReturn['operation'] = "changed";
$toReturn['date'] = $item->updated_at;
$toReturn['diff'] = Carbon::parse($item->updated_at)->diffForHumans();
} else {
$toReturn['operation'] = "delete";
$toReturn['date'] = $item->deleted_at;
$toReturn['diff'] = Carbon::parse($item->deleted_at)->diffForHumans();
}
return $toReturn;
});
$conditions = $user->conditions()
->withTrashed()
->orderBy('updated_at', 'desc')
->get();
$transformed2 = $conditions->transform(function($item, $key) use($user) {
$toReturn = [];
$toReturn['type'] = "calculation";
$toReturn['name'] = $item->name;
$toReturn['user'] = $this->getUserById($item->user_id);
if($item->created_at == $item->updated_at && $item->deleted_at == null) {
$toReturn['operation'] = "saved";
$toReturn['date'] = $item->created_at;
$toReturn['diff'] = Carbon::parse($item->created_at)->diffForHumans();
} elseif($condition->created_at != $condition->updated_at && $condition->deleted_at != null){
$toReturn['operation'] = "changed";
$toReturn['date'] = $item->updated_at;
$toReturn['diff'] = Carbon::parse($item->updated_at)->diffForHumans();
} else {
$toReturn['operation'] = "delete";
$toReturn['date'] = $item->deleted_at;
$toReturn['diff'] = Carbon::parse($item->deleted_at)->diffForHumans();
}
return $toReturn
});
$merged = $transform->merge($transform2);
Building on #devk 's answer here is a neater version without so much repetitive code:
/**
* Transform a collction with a given callback
*
* #param Collection $collection A laravel collection
* #param User $user A User object
* #return Collection
**/
private function transformCollection(Collect $collection, User $user) {
return $collection->transform(function($item, $key) use ($user) {
$toReturn = [
'type' => 'calculation',
'name' => $item->name,
'user' => $user->name
];
if ($item->created_at == $item->updated_at && $item->deleted_at == null) {
$toReturn['operation'] = "saved";
$toReturn['date'] = $item->created_at;
$toReturn['diff'] = Carbon::parse($item->created_at)->diffForHumans();
} elseif ($item->created_at != $item->updated_at && $item->deleted_at != null) {
$toReturn['operation'] = "changed";
$toReturn['date'] = $item->updated_at;
$toReturn['diff'] = Carbon::parse($item->updated_at)->diffForHumans();
} else {
$toReturn['operation'] = "delete";
$toReturn['date'] = $item->deleted_at;
$toReturn['diff'] = Carbon::parse($item->deleted_at)->diffForHumans();
}
return $toReturn;
});
}
// Return all user calculations ordered by when they were updated including deleted
$calculations = $user->calculations()->withTrashed()->orderBy('updated_at', 'desc')->get();
$conditions = $user->conditions()->withTrashed()->orderBy('updated_at', 'desc')->get();
// Transform both collections
$transformed = transformCollection($calculations, $user);
$transformed2 = transformCollection($conditions, $user);
// Merge the resulting collections into a single collection
$merged = $transform->merge($transform2);
Edit
If your Calculation object has a model you can also make sure that the dates are returned as Carbon dates by adding them to the protected $dates = [] array
protected $dates = [
'deleted_at',
'created_at',
'updated_at'
];
I think that created_at and updated_at are included in this by default as part of BaseModel, thought i could well be wrong.

Query in Api Laravel

I'm trying to make APIs showing data from two tables, but I'm stuck at this point.
This is my ApiController:
public function postDetaillog(Request $request)
{
$response = array();
$validator = Validator::make(
$request->all(),
[
'id'=> 'required',
]
);
if ($validator->fails()) {
$message = $validator->errors()->all();
$result['api_status'] = 0;
$result['api_message'] = implode(', ',$message);
$res = response()->json($result);
$res->send();
exit;
}
$data = DB::table('log_patrols')
->where('id', $request->input('id'))
->first();
$site = asset("uploads").'/';
$result = DB::table('log_patrol_details')
->select("*",DB::raw("concat('$site',photo1) as photo1"),DB::raw("concat('$site',photo2) as photo2"),DB::raw("concat('$site',photo3) as photo3"))
->where('id', $request->input('id'))
->first();
if (count($result) == 0) {
$response['api_status'] = count($result);
$response['api_message'] = "No data";
} else {
$response['api_status'] = 1;
$response['api_message'] = "success";
$response['data'] = $data;
$response['result'] = $result;
}
return response()->json($response);
}
first table
second table
Whenever I try to get the results, it always gives me 0 = no data
Could you please help me?
If what you get is a collection you may use if ($result->count() == 0) to check if it is empty.
Change as follows:
if ($result->count() == 0) {
$response['api_status'] = 0; // Don't use useless logic
$response['api_message'] = "No data";
} else {
$response['api_status'] = 1;
$response['api_message'] = "success";
$response['data'] = $data;
$response['result'] = $result;
}

Laravel : search or filter the collection

I have this issue while filtering or searching through a collection
http://laravel.io/bin/vj115 check the url for code.
What i am trying to do is filter a collection by get method (from url ofcourse)
But only it only works when Input::get('category') has value else nothing works.
Could you please check the code and let me know what need to be fixed?
Thanks.
===== Real Code just incase the link is broken in future (edited)=============
public function anyIndex() {
$id = Input::get('id');
$brand = Brand::firstOrNew(array('id' => $id));
$paginate = Misc::getSettings('admin-pagination');
$page_no = isset($_GET['page']) ? $_GET['page'] : 1;
$i = ($paginate * $page_no) - ($paginate - 1);
$appends = false;
$newBrands = new Brand;
if (Input::get('category')) {
$brandCat = BrandCategory::find(Input::get('category'));
$newBrands = $brandCat->brands();
$appends['category'] = Input::get('category');
}
if (Input::get('status')) {
$status = Input::get('status') == 'published' ? 1 : 0;
$newBrands->where('is_active', '=', $status);
$appends['status'] = Input::get('status');
}
if (Input::get('order_by') || Input::get('order')) {
if (Input::get('order_by')) {
$order_by = Input::get('order_by');
$appends['order_by'] = Input::get('order_by');
} else {
$order_by = 'name';
}
if (Input::get('order')) {
$order = Input::get('order');
$appends['order'] = Input::get('order');
} else {
$order = 'asc';
}
$order = Input::get('order') ? Input::get('order') : 'asc';
$newBrands->orderBy($order_by, $order);
}
$brands = $newBrands->paginate($paginate);
$brand_categories_list = new BrandCategory;
$selected_cats = array();
if ($id != "") {
$selected_cats = $brand->categories->lists('id');
}
return View::make('admin.brands.index')
->with(array(
'selected_cats' => $selected_cats,
'brand' => $brand,
'brands' => $brands,
'brand_categories_list' => $brand_categories_list->lists('name', 'id'),
'appends' => $appends,
'i' => $i
));
}
Thanks to Dave.. I solved it as :
public function anyIndex() {
$id = Input::get('id');
$brand = Brand::firstOrNew(array('id' => $id));
$paginate = Misc::getSettings('admin-pagination');
$page_no = isset($_GET['page']) ? $_GET['page'] : 1;
$i = ($paginate * $page_no) - ($paginate - 1);
$appends = false;
if (Input::has('category')) {
$brandCat = BrandCategory::find(Input::get('category'));
$newBrands = $brandCat->brands();
$appends['category'] = Input::get('category');
} else {
$newBrands = Brand::limit(-1);
}
if (Input::has('status')) {
$status = Input::get('status') == 'published' ? 1 : 0;
$newBrands->where('is_active', '=', $status);
$appends['status'] = Input::get('status');
}
if (Input::has('order_by') || Input::has('order')) {
if (Input::has('order_by')) {
$order_by = Input::get('order_by');
$appends['order_by'] = Input::get('order_by');
} else {
$order_by = 'name';
}
if (Input::has('order')) {
$order = Input::get('order');
$appends['order'] = Input::get('order');
} else {
$order = 'asc';
}
$order = Input::get('order') ? Input::get('order') : 'asc';
$newBrands->orderBy($order_by, $order);
}else{
$newBrands->orderBy('name', 'asc');
}
$brands = $newBrands->paginate($paginate);
/* $queries = DB::getQueryLog();
$last_query = end($queries);
dd($last_query); */
$brand_categories_list = new BrandCategory;
$selected_cats = array();
if ($id != "") {
$selected_cats = $brand->categories->lists('id');
}
return View::make('admin.brands.index')
->with(
array(
'selected_cats' => $selected_cats,
'brand' => $brand,
'brands' => $brands,
'brand_categories_list' => $brand_categories_list->lists('name', 'id'),
'appends' => $appends,
'i' => $i)
);
}
I suspect it has to do with how you are using Eloquent. You can't simply apply methods to the object if it was created using the "new" keyword.
$newBrands = new Brand;
// This won't work
$newBrands->where('is_active', '=', $status);
// This will work
$newBrands = $newBrands->where('is_active', '=', $status);
It will work if you create it statically along with a method.
$newBrands = Brand::limit(100);
// This will work
$newBrands->where('is_active', '=', $status);
Fluent (DB) works the same way.
$newBrands = DB::table('brands');
// This wil work
$newBrands->where('is_active', '=', $status);
here I am searching the username(s) based on the displayname or fullname or email. therefore, the $request->filled('name of your input') is the solution.
$usernames = (new User())->newQuery(); //where User is the model
if($request->filled('email')){
$usernames->orWhere('email',$request->email);
}
if($request->filled('full_name')){
$usernames->orWhere('full_name',$request->full_name);
} if($request->filled('display_name')){
$usernames->orWhere('display_name',$request->display_name);
}
$usernames = $usernames->pluck('username')->toArray();

Want to remove (((price_table_price.value)*1) < from the product collection

I am very new to Magento. (Indeed this is my first task). I would be very glad if you can help me on this.
I am using magento sample database and theMagento version is 1.3.2.
Local PC URL : http://magento.local/electronics/cell-phones.html?price=4,100
Class : Mage_Catalog_Block_Product_List
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getSingleton('catalog/layer');
/* #var $layer Mage_Catalog_Model_Layer */
if ($this->getShowRootCategory()) {
$this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
}
// if this is a product view page
if (Mage::registry('product')) {
// get collection of categories this product is associated with
$categories = Mage::registry('product')->getCategoryCollection()
->setPage(1, 1)
->load();
// if the product is associated with any category
if ($categories->count()) {
// show products from this category
$this->setCategoryId(current($categories->getIterator()));
}
}
$origCategory = null;
if ($this->getCategoryId()) {
$category = Mage::getModel('catalog/category')->load($this->getCategoryId());
if ($category->getId()) {
$origCategory = $layer->getCurrentCategory();
$layer->setCurrentCategory($category);
}
}
$this->_productCollection = $layer->getProductCollection();
$this->prepareSortableFieldsByCategory($layer->getCurrentCategory());
if ($origCategory) {
$layer->setCurrentCategory($origCategory);
}
}
return $this->_productCollection;
}
I need to remove (((price_table_price.value)*1) < 400) from the $this->_productCollection.
Can’t figure out how and when this added to the product collection. Please HELP!!!
Thanks!!!!
Since No one helped me, I figured out answer by myself.
Firstly I'll state what my task was.
Lets say that I have a products 10 in 100-200 price range, 12 in 500-600 and 1 product in 10000-20000 of X category. With the default price range of magento it display as two ranges which are 0-10000 and 10000-200000 which is not much useful for the customer.
I had to made the ranges as 100-200,500-600 and 1000<
I'll post all my code here.
When I follow other post for customizing ranges most of them have only consider display of the layered navigation. But here I have made my consideration on displaying the products when click on the final range (i.e. 1000<)
Please note that LMage is local->LMage folder and also I am a new bee for the Magento ;).
Please post here if you find a better way to do this.
class LMage_CatalogIndex_Model_Mysql4_Price extends Mage_CatalogIndex_Model_Mysql4_Price {
public function getCount($range, $attribute, $entitySelect) {
$select = clone $entitySelect;
$select->reset(Zend_Db_Select::COLUMNS);
$select->reset(Zend_Db_Select::ORDER);
$select->reset(Zend_Db_Select::LIMIT_COUNT);
$select->reset(Zend_Db_Select::LIMIT_OFFSET);
$select->join(array('price_table' => $this->getMainTable()), 'price_table.entity_id=e.entity_id', array());
$response = new Varien_Object();
$response->setAdditionalCalculations(array());
if ($attribute->getAttributeCode() == 'price') {
$select->where('price_table.customer_group_id = ?', $this->getCustomerGroupId());
$args = array(
'select' => $select,
'table' => 'price_table',
'store_id' => $this->getStoreId(),
'response_object' => $response,
);
Mage::dispatchEvent('catalogindex_prepare_price_select', $args);
}
$fields = array('count' => 'COUNT(DISTINCT price_table.entity_id)', 'range' => "FLOOR(((price_table.value" . implode('', $response->getAdditionalCalculations()) . ")*{$this->getRate()})/{$range})+1");
$select->from('', $fields)
->group('range')
->where('price_table.website_id = ?', $this->getWebsiteId())
->where('price_table.attribute_id = ?', $attribute->getId());
$result = $this->_getReadAdapter()->fetchAll($select);
$counts = array();
foreach ($result as $row) {
if ($row['range'] >= 11) {
$counts[11] = isset($counts[11])?$row['count']+$counts[11]:$row['count'];
} else {
$counts[$row['range']] = $row['count'];
}
}
return $counts;
}
public function applyFilterToCollection($collection, $attribute, $range, $index, $tableName = 'price_table') {
/**
* Distinct required for removing duplicates in case when we have grouped products
* which contain multiple rows for one product id
*/
$collection->getSelect()->distinct(true);
$tableName = $tableName . '_' . $attribute->getAttributeCode();
$collection->getSelect()->joinLeft(
array($tableName => $this->getMainTable()), $tableName . '.entity_id=e.entity_id', array()
);
$response = new Varien_Object();
$response->setAdditionalCalculations(array());
$collection->getSelect()
->where($tableName . '.website_id = ?', $this->getWebsiteId())
->where($tableName . '.attribute_id = ?', $attribute->getId());
if ($attribute->getAttributeCode() == 'price') {
$collection->getSelect()->where($tableName . '.customer_group_id = ?', $this->getCustomerGroupId());
$args = array(
'select' => $collection->getSelect(),
'table' => $tableName,
'store_id' => $this->getStoreId(),
'response_object' => $response,
);
Mage::dispatchEvent('catalogindex_prepare_price_select', $args);
}
$collection->getSelect()->where("(({$tableName}.value" . implode('', $response->getAdditionalCalculations()) . ")*{$this->getRate()}) >= ?", ($index - 1) * $range);
if($index<=10){
$collection->getSelect()->where("(({$tableName}.value" . implode('', $response->getAdditionalCalculations()) . ")*{$this->getRate()}) < ?", $index * $range);
}
return $this;
}
public function getCategoryProductPrices($attribute = null, $entitySelect) {
$select = clone $entitySelect;
$select->reset(Zend_Db_Select::COLUMNS);
$select->reset(Zend_Db_Select::ORDER);
$select->reset(Zend_Db_Select::LIMIT_COUNT);
$select->reset(Zend_Db_Select::LIMIT_OFFSET);
$response = new Varien_Object();
$response->setAdditionalCalculations(array());
$select->join(array('price_table' => $this->getMainTable()), 'price_table.entity_id=e.entity_id', array());
if ($attribute->getAttributeCode() == 'price') {
$select->where('price_table.customer_group_id = ?', $this->getCustomerGroupId());
$args = array(
'select' => $select,
'table' => 'price_table',
'store_id' => $this->getStoreId(),
'response_object' => $response,
);
Mage::dispatchEvent('catalogindex_prepare_price_select', $args);
}
$select
->from('', "(price_table.value" . implode('', $response->getAdditionalCalculations()) . ")")
->where('price_table.website_id = ?', $this->getWebsiteId())
->where('price_table.attribute_id = ?', $attribute->getId());
return $this->_getReadAdapter()->fetchAll($select);
}
}
class LMage_CatalogIndex_Model_Price extends Mage_CatalogIndex_Model_Price{
public function getCategoryProductPrices($attribute, $entityIdsFilter){
return $this->_getResource()->getCategoryProductPrices($attribute, $entityIdsFilter);
}
}
class LMage_Catalog_Model_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Filter_Price {
public function getPriceRange() {
$range = $this->getData('price_range');
if (is_null($range)) {
$productsprice = $this->getCategoryProductPricesArr();
$maxPrice = $this->getMaxPriceInt();
$maxPrice = $this->getMaxPriceOfMaxOccurenceRange($productsprice, $maxPrice);
$index = 1;
do {
$range = pow(10, (strlen(floor($maxPrice)) - $index));
$items = $this->getRangeItemCounts($range);
$index++;
} while ($range > self::MIN_RANGE_POWER && count($items) < 1);
$this->setData('price_range', $range);
}
return $range;
}
public function getMaxPriceOfMaxOccurenceRange($productsprice, $maxPrice) {
$rangeArr = array();
$i = 1;
$val = 0;
do {
$val = self::MIN_RANGE_POWER * $i - 1;
$rangeArr[$val] = 0;
$i *= 10;
} while ($maxPrice > $val);
foreach ($productsprice as $value) {
$rangeArr[pow(10, strlen(floor($value['value']))) - 1]+=1;
}
return array_search(max($rangeArr), $rangeArr);
}
public function getCategoryProductPricesArr() {
$productsprice = $this->getData('products_price_arr');
if (is_null($productsprice)) {
$productsprice = Mage::getSingleton('catalogindex/price')->getCategoryProductPrices(
$this->getAttributeModel(), $this->_getBaseCollectionSql()
);
$this->setData('products_price_arr', $productsprice);
}
return $productsprice;
}
/**
* Prepare text of item label
*
* #param int $range
* #param float $value
* #return string
*/
protected function _renderItemLabel($range, $value) {
$store = Mage::app()->getStore();
if ($value > 10) {
$fromPrice = $store->formatPrice(($value - 1) * $range);
//$toPrice = $store->formatPrice($value * $range);
return Mage::helper('catalog')->__('%s < ', $fromPrice);
}
$fromPrice = $store->formatPrice(($value - 1) * $range);
$toPrice = $store->formatPrice($value * $range);
return Mage::helper('catalog')->__('%s - %s', $fromPrice, $toPrice);
}

Categories