I am trying to sort eloquent collection using sortByDesc. It works for first sorting but chaining with more columns doesn't give proper result. Here is the query and code I am trying
$data = Divrank::where('division_id', $id)->with(['team.player1', 'team.player2'])->with('meta')->orderBy('position', 'asc')->get();
foreach($data as $k=>$t){
if ($t->meta) { // it has ranks informations
$t->totalSets = $t->meta->totalSets;
$t->totalGames = $t->meta->totalGames;
$t->points = $t->meta->points;
} else {
$t->totalSets = 0;
$t->totalGames = 0;
$t->points = 0;
}
unset($data[$k]->meta);
}
//return $data;
return $data->sortByDesc('points')->sortByDesc('totalSets')->sortByDesc('totalGames');
If I remove ->sortByDesc('totalSets')->sortByDesc('totalGames') then it shows correct formate.
Any ideas how to achieve this? Thank you.
Ok, got it, I need to do reverse sorting. $data->sortByDesc('totalGames')->sortByDesc('totalSets')->sortByDesc('points'); this works. It will sort first with games, then sets and then points..
Related
Is there a better way to refactor this code? It's basically the same line with different values. I thought of doing a for loop but maybe there's another way.
$date = $request->date;
$underConsideration = Application::whereDate('created_at',$date)->where('status','Under consideration')->count();
$phoneScreened = Application::whereDate('created_at',$date)->where('status','Phone screened')->count();
$interviewed = Application::whereDate('created_at',$date)->where('status','Interviewed')->count();
$offerExtended = Application::whereDate('created_at',$date)->where('status','Offer extended')->count();
You should create a separate method for this.
public function myMethod()
{
$under_consideration = $this->fetchApplicationData($request, 'Under consideration');
$phone_screened = $this->fetchApplicationData($request, 'Phone screened');
$interviewed = $this->fetchApplicationData($request, 'Interviewed');
$offer_extended = $this->fetchApplicationData($request, 'Offer extended');
}
private function fetchApplicationData($request, $status)
{
return Application::
whereDate('created_at', $request->date)
->where('status', $status)
->count();
}
That is a much cleaner code.
However, I advise that you should put the items:
Under consideration, Phone screened, Interviewed, Offer extended
into a separate table on the database and just save the status_id on your main table.
One of the major advantage on this is the speed. For example, your client wants to know all record that has a status of Interviewed for a certain date span. Database searching against integer is a lot faster than string.
You could create a method to handle the select operations. Something like:
public function yourExisitingMethod() {
$date = $request->date;
$underConsideration = getData($date,'Under consideration');
$phoneScreened = getData($date,'Phone screened');
$interviewed = getData($date,'Interviewed');
$offerExtended = getData($date,'Offer extended');
}
public function getData($date, $status) {
$data = Application::whereDate('created_at',$date)->where('status',$status)->count();
return $data;
}
This would at the very least improve the maintainability of your code, and in my opinion improves reusability and readability.
I have a parsing problem where I want to get all of the people with a particular subscription but not people who have another type of subscription. The subscriptions are stored in a comma delineated list in the subscriptions table in the subscriptions column. Here is the code I have so far:
$includeQuery = [];
foreach ($includeSegment as $include) {
$singleQuery = ['subscriptions','like', '%'.$include.'%', 'or'];
array_push($includeQuery, $singleQuery);
}
$excludeQuery = [];
foreach ($excludeSegment as $exclude) {
$singleQuery = ['subscriptions', 'not like', '%'.$exclude.'%', 'or'];
array_push($excludeQuery, $singleQuery);
}
$included = Subscription::where($excludeQuery)->where($includeQuery)->get();
I get results back but some of them have the excluded subscriptions in them.
use whereIn and whereNotIn instead :
Subscription::whereIn($includeSegment)->whereNotIn($excludeSegment)->get();
then you dont need to also iterate segments once they are arrays of strings
The problem with code above was in the boolean parameter I had "or" instead of "and". So only if all of the subscriptions for a particular user were present would the record get thrown out. Here is the updated code:
$includeQuery = [];
foreach ($includeSegment as $include) {
$singleQuery = ['subscriptions','like', '%'.$include.'%', 'or'];
array_push($includeQuery, $singleQuery);
}
$excludeQuery = [];
foreach ($excludeSegment as $exclude) {
$singleQuery = ['subscriptions', 'not like', '%'.$exclude.'%', 'and'];
array_push($excludeQuery, $singleQuery);
}
// $included = Subscription::where($excludeQuery)->where($includeQuery)->get();
$included = DB::table('subscriptions')
->join('app_users', 'app_users.customer_number', '=', 'subscriptions.customer_number')
->join('app_datas', 'app_datas.customer_number', '=', 'subscriptions.customer_number')
->where($includeQuery)
->where($excludeQuery)
->select('app_datas.device_token')
->get();
All warehouses tables have differemt number of columns. So I can't use union inside a query. But I hate this way to join this collection of objects.
There is a better (clear) way?
Thx :)
public function index()
{
$warehouses1 = Farm_warehouse::all();
$warehouses2 = Butchery_warehouse::all();
$warehouses3 = Grape_warehouse::all();
$warehouses4 = Iron_warehouse::all();
$warehouses5 = Rice_warehouse::all();
$warehouses6 = Silk_warehouse::all();
$warehouses7 = Wood_warehouse::all();
$warehouses2 = $warehouses1->merge($warehouses2);
$warehouses3 = $warehouses2->merge($warehouses3);
$warehouses4 = $warehouses3->merge($warehouses4);
$warehouses5 = $warehouses4->merge($warehouses5);
$warehouses6 = $warehouses5->merge($warehouses6);
$warehouses = $warehouses6->merge($warehouses7);
return view('warehouses.index', compact('warehouses'));
}
This may not be the improvement you are looking for but couldn't you chain it together like this?
public function index()
{
$warehouses = Farm_warehouse::all();
$warehouses->merge(Butchery_warehouse::all());
$warehouses->merge(Grape_warehouse::all());
$warehouses->merge(Iron_warehouse::all());
$warehouses->merge(Rice_warehouse::all());
$warehouses->merge(Silk_warehouse::all());
$warehouses->merge(Wood_warehouse::all());
return view('warehouses.index', compact('warehouses'));
}
I think that's a bit easier to read, but may be you can extract it out to a base Warehouse Model or try digging into the Collection class for something more fruitful. Hope this helps.
I'm looking to have the normal quick search, with the addition of one feature: results from a given category come first.
So far I have modified protected function _getProductCollection() in Mage_CatalogSearch_Block_Result and this works, but it ignores the custom search results (e.g. by price or name) which I want to be applied within the two groups of results.
My additional code is:
$initial = $this->_productCollection->getAllIds();
$this->_productCollection->addCategoryFilter(Mage::getModel('catalog/category')->load(3));
$newids = $this->_productCollection->getAllIds();//$this->_productCollection->getAllIds();
$merged_ids = array_merge($newids, $initial);
$merged_ids = array_unique($merged_ids);
$this->_productCollection->addCategoryFilter(Mage::getModel('catalog/category')->load(2));
$this->_productCollection->getSelect()->order("find_in_set(e.entity_id,'".implode(',',$merged_ids)."')");
Where cat 2 is the root category.
So, where is the collection being sorted? If I move this there that should do the trick I believe (?).
It may not work in everyone's situation, but adding the following worked for me:
$this->_productCollection->setOrder($this->getRequest()->getParam('order'), $this->getRequest()->getParam('dir'));
So I ended up with a protected function _getProductCollection() of:
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$this->_productCollection = $this->getListBlock()->getLoadedProductCollection();
}
$this->_productCollection->setOrder($this->getRequest()->getParam('order'), $this->getRequest()->getParam('dir'));
$initial = $this->_productCollection->getAllIds();
$this->_productCollection->addCategoryFilter(Mage::getModel('catalog/category')->load(3));
$newids = $this->_productCollection->getAllIds();//$this->_productCollection->getAllIds();
$merged_ids = array_merge($newids, $initial);
$merged_ids = array_unique($merged_ids);
$this->_productCollection->addCategoryFilter(Mage::getModel('catalog/category')->load(2));
$this->_productCollection->getSelect()->order("find_in_set(e.entity_id,'".implode(',',$merged_ids)."')");
return $this->_productCollection;
}
I want to show all bundles on a simple product's page and so need to retrieve the information. I searched and tried a lot. This post sounds promising, but is either not working or maybe not for my problem:
Magento - get a list of bundled product ids from a product id
I found a solution for grouped products but this can't be applied here.
$grouped_product_model = Mage::getModel('bundle/product_selection');
$groupedParentId = $grouped_product_model->getParentIdsByChild($product->getId());
I found the table catalog_product_bundle_selection to be the right place to search, but I wonder if there is a clean way and existing function to search this table by product_id than just to hack this.
I didn't find a solution in Mage_Bundle.
What did I miss?
After getting first aid from vrnet I wrote a new block class, so I can update the layout
class Thomaier_Catalog_Block_Product_View_BundledSelect extends Mage_Catalog_Block_Product_View
{
protected $_simpleProducts = array( '3' ); // just an example
public function getBundles() {
$bundleIds = array();
$bundlesCollectionModel = Mage::getResourceModel('bundle/selection_collection');
$bundlesCollection = $bundlesCollectionModel->getSelect()
->where('`selection`.`product_id` in (' . join(',', (array)$this->_simpleProducts) . ')');
foreach ($bundlesCollection as $bundleItem) {
$bundleIds[] = $bundleItem->getParentProductId();
}
...
}
}
I skipped some parts. As I mentioned in the comment, the SQL query works fine when I try it in phpmyadmin, but $bundleItem is not created and ->load() throws an exception.
Thanks for advice.
Below is a method I wrote for a client having the same request with an extra : the ability to shuffle the result.
Hope it helps.
protected $_simpleProducts = array(); // Array with IDs of simple products you want bundles from.
protected $_shuffle = false;
public function getBundles() {
$bundleIds = array();
/*Rather than using a collection model
and make operations with getSelect,
a more elegant way is to extend
Mage_Bundle_Model_Mysql4_Selection_Collection
with a method that would be something like
setProductIdsFilter($productIds)*/
$bundlesCollectionModel = Mage::getResourceModel('bundle/selection_collection');
$bundlesCollection = $bundleCollectionModel->getSelect()
->where('`selection`.`product_id` in (' . join(',', (array)$this->_simpleProducts) . ')');
foreach ($bundlesCollection as $bundleItem) {
$bundleIds[] = $bundleItem->getParentProductId();
}
if (count($bundleIds)) {
$allowBundles = Mage::getResourceModel('catalog/product_collection')
->addIdFilter($bundleIds)
->addFieldToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
if ($this->_shuffle) {
$allowBundles->getSelect()->order('rand()');
}
if ($allowBundles->count()) {
return $allowBundles;
}
}
return;
The following is the best way to work with these. This way you do not rely on a custom query but instead you can use the core methods:
$bundlesCollection = Mage::getResourceModel('bundle/selection')
->getParentIdsByChild($simple_product_ids_array_or_int);
foreach ($bundlesCollection as $bundleProdId) {
//do anything you want with the bundleProdId array elements
}