I'm manually building up a report in Magento using collections and I'm trying to make this use the order completion date instead of the order created date.
My current code is:
$orders = Mage::getModel('sales/order')->getCollection()
->addAttributeToFilter('created_at', array('from'=>$fromDate, 'to'=>$toDate))
->addAttributeToFilter('status', array('eq' => Mage_Sales_Model_Order::STATE_COMPLETE))
->addAttributeToFilter('store_id', array('eq' => 2));
I've found the following question where the user suggest manually logging all of the status changes for each order manually.
Finding out when an order status has been set to completed
As I'm wanting to use this in a collection I don't believe this is a suitable way, also I somewhat expect this sort of information to be accessible in Magento.
Thanks,
You can retrieve a collection of the order-status-history updates:
$collection = Mage::getResourceModel('sales/order_status_history_collection')
->addAttributeToSelect('created_at', 'parent_id')
->addAttributeToFilter('status', array('eq'=>'complete'))
->load();
After which you can iterate the $collection and extract the parent_id and the created_at for the information you want.
Related
I have a query returning offers by a given key. This is all functioning well, but I need my application to add a custom key which tells the frontend which offer is the lowest of them all (in price).
How do I achieve this?
My current query:
$offers = Offer::with('user:id,fname', 'review')
->where('isbn', $isbn)
->where('match_id', null)
->orderBy('price', 'ASC')
->paginate(5);
As a novice to laravel I am hoping I can get to the bottom of this rather irritating issue!
I have a small app that consists of 2 user types, Buyers and Providers, The usertype->buyers can request a free estimation for a service they require and the provider can create this manually or have an estimation sent automatically based on what they set as there default value for that specific price range so for example if a user(buyer) requests an estimation for a service that is £200 the provider may have set a default estimation of £180 - £220 for that price range and this is what will be shown to the user.
The problem I have is to make it fair we use the random function within laravel to randomly select 5 providers from the providers_table along with their default estimation and show this to the user from orderBy in descending order and looping through the results in the view.
$projectbids = ProjectBids::where('provider_id', '=', $proid)
->where('category_id', '=', $catid)
->orderBy('bid_price', 'desc')
->get()->random(5);
foreach($projectbids as $bid)
{{ $bid->bid_price }}
endforeach
So I'm trying to find a way to insert the 5 displayed estimations into a saved_estimates table so if the user refreshes the page or comes back to the page the model and view will not reorder the providers results based from the random(5) function that gets called.
I'm aware of this question: Create a Insert... Select statement in Laravel but wasn't to sure if there could be a better or easier way of doing this as my problem lays where I'm looping through the 5 results provided to the view from the table.
In a nutshell: I want to be able to store the 5 dynamic results straight into a saved_estimations table with several columns such as project_id, provider_id, user_id, estimated_price so the user can come back to their saved estimations in the future without them changing.
Very grateful for any input and advice, it will be very helpful to see what the more experienced users would suggest.
Thanks
-- Updated personal approach to see if there is room for improvement and to make it more laravel friendly.
$results = $bidders;
foreach($results as $row){
$project = $projectid;
$category = $row->category_id;
$provider = $row->service_providers_id;
$bidprice = $row->bid_price;
$propvalue = $row->property_value_id;
DB::table('static_bids')->insert(array(
'project_id' => $project,
'category_id' => $category,
'service_providers_id' => $provider,
'bid_price' => $bidprice,
'property_value_id' => $propvalue
));
}
All you need is to use simple insertions into the table, something like this:
foreach ($projectbids as $bid) {
$result = SavedEstimation::create(array(
'project_id' => $bid->project_id,
'provider_id'=> $bid->provider_id,
'user_id' => $bid->user_id,
'estimated_price' => $bid->estimated_price
));
}
There is no way to insert this by using just one query anyway. You could simply store output HTML if the only reason you want to do this is to show same HTML to the user later, but this is bad practice.
Given a product id, I can query the product using
Mage::getModel('catalog/product')->load($id);
What I have is a list of ids (comma separated), I can explode it, loop through each id, and run load($id) like above. I am concern a bit about the performance. Is this a different way to handle it, something like where clause, with an IN(id1,id2,id3,id4) kind of syntax. I google around, and I see this
Mage::getModel('catalog/product')->getCollection()->addAtributeToSelect('*')
I think I can add a filter to this, right? Had anyone solve a similar problem? Thank you very much.
1) Filter your collection using Product Ids you have :
$productIds = explode(',', "1,2,3,4,5,6");
$collection = Mage::getModel('catalog/product')->getCollection()-
>addAttributeToFilter('entity_id', array('in' => $productIds));
2) If you want to retrive only specific information like name & sku etc, you can add attribute to select, this means collection will only fetch the name from database tables, rather than whole product information, you can select with below code
$collection->addAttributeToSelect(array('name','sku'));
3) Make Sure All this code is written in blocks or models and not in Phtmls, or else it can definitely affect the page speed.
As par r requirement you can use finset function of magento which accepts array as parameter
Try to use addAttributeToFilter with or condition
$collection->addAttributeToFilter($attribute,
array(
array('finset'=> array('237')),
array('finset'=> array('238')),
array('finset'=> array('239')),
)
);
Or
$collection->addAttributeToFilter(
array(
array('attribute'=> 'attributecode','finset' => array('237')),
array('attribute'=> 'attributecode','finset' => array('237')),
array('attribute'=> 'attributecode','finset' => array('237')),
)
);
Hiho everybody! I hope you'll give me a clue about this because I'm still noob with Magento.
I try to display a list of products I get in an array. In Mage/Catalog/Block/Product/List.php, I created a new Varien_Data_Collection() in which I pushed my products objects (with ->addItem($product)).
Then I return my custom collection and List.php class does his work with it to display the list of products.
When I call the page in my browser, I had the right number of displayed products and when I click on it to see the product page, I get the right page.
However, all the data (like the product name, the price, etc) are empty. I guess that the methods used by List class to catch these data fail with my Varien_Data_Collection object.
To illustrate, here is my code sample :
// getting a particular product
$mainProduct = Mage::getModel('catalog/category')->load($currentCat->getId());
$mainProduct = $mainProduct->getProductCollection();
$mainProduct = $mainProduct->addAttributeToFilter('product_id', $_GET['cat_id']);
// creating a custom collection
$myCollection = new Varien_Data_Collection();
foreach ($mainProduct as $product) {
// getting my particular product's related products in an array
$related = $product->getRelatedProductIds();
if ($this->array_contains($related, $_GET['cat_id'])) {
// if it suits me, add it in my custom collection
$myCollection->addItem($product);
}
}
return $myCollection;
And this is what I get in my list page :
When I var_dump($myCollection), I can see that ['name'], ['price'], etc fields are not referenced. Only ['product_id'] and many other fields I don't care about.
My very ultimate question is : how can I return a collection containing these products data to my List class ? I know that it is poorly explained but my English is very limited and I try to do my best :(
Calling ->getProductCollection() against a category only returns skeleton data for each product in the created collection. If you want full data for each of the products, you need to then load them, so in your foreach loop you would have:
$product = Mage::getModel('catalog/product')->load($product->getId());
However the way in which you are building the collection is not the best working practice - you should never have to create your own Varien_Data_Collection object, instead you should be creating a product collection as follows:
$collection = Mage::getModel('catalog/product')->getCollection();
Then before you load the collecion (which the foreach loop or calling ->load() against the collection will do as 2 examples), you can filter the collection according to your requirements. You can either do this using native Magento methods, one of which you are already using (addAttributeToFilter()) or I prefer to pull the select object from the collection and apply filtering this way:
$select = $collection->getSelect();
You can then run all of the Zend_Db_Select class methods against this select object to filter the collection.
http://framework.zend.com/manual/1.12/en/zend.db.select.html
When the collection has been loaded, the products inside it will then contain full product data.
first of all pelase do not use $_GET variable, use Mage::app()->getRequest()->getParams();
second why not try to build your collection correctly from the start?
here is what your code does:
$mainProduct = Mage::getModel('catalog/category')->load($currentCat->getId());
$mainProduct = $mainProduct->getProductCollection();
$mainProduct = $mainProduct->addAttributeToFilter('product_id', $_GET['cat_id']);
get one product, I mean you load a category then load a product collection, then filter by product id.. why not:
$mainProduct = Mage::getModel('catalog/product')->load($yourSearchedId);
I aslo do not see why you filter products by $_GET['cat_id'] which looks like a category id...
To conclude you can get more help if you explain exactly what you are trying to find. It looks like you are trying to find all products that have a given product as related. So why not set for that given product the related product correctly and get the related products collection.
$_product->getRelatedProductCollection();
UPDATE:
now that you cleared your request try this:
$relatedIds = $product->getRelatedProductIds();
$myCollection = Mage::getModel('catalog/category')
->load($currentCat->getId())
->getProductCollection();
$myCollection->addAttributeToFilter('product_id', array("in",$relatedIds));
//also addAttributeToSelect all attributes you may need like name etc
$myCollection->load(); //maybe you don't actualy need to load here
Please bear in mind I did not test this code it was written from teh top of my head, test it. But I hope you got the idea.
I have developed a custom search engine for our Magento store and I am trying to load the product collection in a very specific order (I have ranked the results according to an algorithm I designed).
I can load the product collection correctly, however it is not in the order that I would like it to be in. Here is basically how it is working now:
My database query basically comes back with a PHP array of product IDs. For this example lets say it looks like this:
$entity_ids = array(140452, 38601 );
Now I can transpose the 140452 and the 38601 and the product collection comes back in the same order each time. I would like the product collection to be in the same order as the ID of the entity ids.
The code I am using to create my collection is as follows:
$products = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('entity_id', array('in' => $entity_ids))
->setPageSize($results_per_page)
->setCurPage($current_page)
->load();
Is there a way to set the sort order to be the order of the $entity_ids array?
Collections inherit from the class
Varien_Data_Collection_Db
There's a method named addOrder on that class.
public function addOrder($field, $direction = self::SORT_ORDER_DESC)
{
return $this->_setOrder($field, $direction);
}
So, you'd think something like this should work for basic ordering
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addOrder('entity_id');
However, it doesn't. Because of the complex joining involved in EAV Collections, there's a special method used to add an attribute to the order clause
Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection::addAttributeToSort
However again, this can only be used to add simple attributes. To create an arbitrary sort, you'll need to manipulate the Zend_Select object directly. I'm not a big fan of this, and I'm not a big fan of using custom mysql functions to achieve things, but it appears it's the only way to do this
I tested the following code on a stock install and got the desired results. You should be able to use it to get what you want.
$ids = array(16,18,17,19);
$products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('entity_id',$ids);
//shakes fist at PDO's array parameter
$ids = array_map('intval', $ids);
$products->getSelect()->order("find_in_set(e.entity_id,'".implode(',',$ids)."')");
foreach($products as $product)
{
var_dump($product->getEntityId());
var_dump($product->getSku());
}
There is no way to sort arbitrarily in SQL so you would have to sort the results in PHP afterwards. Then the bigger problem is you are using page sizing to limit the number of results being returned, some of the records you want might not be returned because of this.
The better solution is to add an attribute to products which you can then use to sort by. Products in categories already have a 'position' value which is used in this way. Then you only need to use the addOrder()addAttributeToSort() method that Alan suggested but with your custom attribute.
(Explanation is hurried, let me know if not clear enough)