I need to retrieve an array of cross sell product ids from a product based on a product id retrieved based on a value in a product custom option.
I have researched how to get it using straight MySQL statements. How do I get it using the standard magento calls?
here is the MySQL process:
Select option_type_id from mage_catalog_product_option_type_title where option_type_id EQ 'desired value';
then:
Select option_id from mage_catalog_product_option_type_value where option_type_id EQ option_type_id; (from above step)
then:
Select product_id from mage_catalog_product_option where option_id EQ option id; (from previous step)
then:
Select linked_product_id from mage_catalog_product_link where product_id EQ product_id (from previous step) AND link_type_id ='5';
(I'm experienced in PHP/MySQL but barely past novice level in Magento)
Can anyone help? Thank you very, very much!
Mark
Try this solution:
$collection = Mage::getModel('catalog/product_link')->getCollection()->addFieldToFilter('option_type_id','desired value’);
$collection->join(array('option' => 'catalog/product_option'), 'main_table.product_id = option.product_id')
->join(array('option_value' => 'catalog/product_option_type_value'), 'option.option_id = option_value.option_id');
var_dump($collection->getFirstItem()->getData());
And this is how it generally works:
$collection = Mage::getModel('catalog/product_option_value')->getCollection()->addFieldToFilter('option_type_id','desired value’);
$collection = Mage::getModel('catalog/product_option')->getCollection()->addFieldToFilter('option_id',$collection->getFirstItem()->getOptionId());
$collection = Mage::getModel('catalog/product_link')->getCollection()->addFieldToFilter('product_id',$collection->getFirstItem()->getProductId());
var_dump($collection->getFirstItem()->getData());
Related
I am trying to append a category id to a large number of SKUs in Magento 1.7. I have used the Import > Append Complex Data and, although it checked the file and ran ok, it did not add these SKUs to the category I wanted them in.
So, the objective is to leave all these SKUs in the categories there are in now but add an additional category.
Any help would be appreciated. Even if it is a different method entirely.
The fastest way to do this is to directly insert this as a SQL query using:
INSERT INTO `catalog_category_product` (
`category_id` ,
`product_id` ,
`position`
)
VALUES (
'4', '34', '0'
), (
'4', '35', '0'
);
In this case, it would add the category Id of 4 to the products with Id 34 and 35. You can create a small PHP script to dynamically create such a query from your file of SKUs and Category Ids.
Reindex after your query was successfully executed.
Alternatively, using the Magento eco-system and not the database, you can do this:
$categoryIds = array();
$toBeUpdatedProducts = array(4,6,7); // all the Ids you want to update
$newCategoryId = 65; // Id of new category
foreach ($toBeUpdatedProducts as $productId) {
$product = Mage::getModel('catalog/product')->load($productId);
$categoryIds = $product->getCategoryIds();
$categoryIds[] = $newCategoryId; // Add new category to existing ones
$product->setCategoryIds($categoryIds);
$product->save();
}
I made this request for get all brands and all items of theses brand with leftJoin :
$brands = Doctrine_Query::create()
->from('Brand b')
->leftJoin('b.Item i')
->fetchArray();
But I want to get only 10 items of each brand, how can I put the limit on Item leftJoin ?
You have to use subquery like this:
->leftJoin('b.Item i WITH i.id IN (SELECT i2.id FROM Item i2 WHERE i2.brand_id=b.id LIMIT 10)')
I didn't test this but it should work.
I know it's late but this actually scored nr 1 on my google search and is unanswered:
Limiting a doctrine query with a fetch-joined collection? suggests using Paginaror object
Here is an example:
My code has Sources that contain rss links and Articles that are articles from the rss feed. So in this example I'll get one Source and all it's articles.
// get the articles (latest first) from source 743
$q=$this->getDoctrine()->getManager()
->createQuery('select s, a from MyCompanyRssBundle:Source s
join s.Articles a
where s.id = :id
order by a.id desc')
->setParameter('id',743);
$q->setMaxResults(1); // this limits Articles to be only 1
// when using $q->getResult();
$sources=new Paginator($q, $fetchJoin = true);
$sources=$sources->getIterator();
// $sources=$q->getResult();
var_dump($sources[0]->getArticles());
I would like to ask you for piece of information that would help me to resolve my issue.
My purpose is to get from the Magento database particular product qty in every order (orders must be in exact definied status). I use batch/script standing apart from Magento but uses Mage:app. I do not know if I should start with models (which seems to be logical approach but slow in the same time) or to work directly on database (which is more difficult).
Thank you for any advice.
Regards,
Querying the database is not that complicated:
SELECT *
FROM sales_flat_order o
LEFT JOIN sales_flat_order_item i ON o.entity_id = i.order_id
WHERE o.status IN ('pending', 'processing')
AND i.product_id = <YOUR_PRODUCT_ID>
total_qty_ordered field in result will represent the ordered quantity.
Getting ordered items quantity through models is not heavy either:
<?php
require_once('app/Mage.php');
umask(0);
Mage::app('default');
$core_resource = Mage::getSingleton('core/resource');
$orders = Mage::getResourceModel('sales/order_collection');
$orders->getSelect()->joinLeft(array('ordered_products' => $core_resource->getTableName('sales/order_item')), 'main_table.entity_id = ordered_products.order_id', array('ordered_products.*'));
$orders->addAttributeToSelect('*')
->addFieldToFilter('status', array('in' => array('pending', 'processing')))
->addAttributeToFilter('main_table.store_id', Mage::app()->getStore()->getId())
->addAttributeToFilter('ordered_products.product_id', array('eq' => '2'));
foreach($orders as $order) {
echo 'Order #' . $order->getId() . ': ' . $order->getData('total_qty_ordered') . '<br/>';
}
The first approach may be a faster but the second one will be Magneto-Upgrade-Safe. So you decide which approach to use.
I'm really, really struggling with what should otherwise be a straightforward query in anything other than LINQ (for example SQL!)
I have two entities:
Product
ProductApprover
The Product entity has a one to many relationship on the ProductApprover entity, e.g:
Product.ProductApprovers gives me all ProductApprover entities relating to the Product.
Getting a Product and associated ProductApprover data is simple enough when querying by my ProductID column on my Product entity as the ProductApprover data associated is bundled into the result automatically, but my problem comes when I want to alter my query by querying data WITHIN my associated ProductApprover entities. I have tried all sorts with use of the 'Where', 'Contains' and 'Any', functions, etc, to perform a subquery, but cannot seem to get the result I want.
The query I want to perform is:
SELECT * FROM Product p
INNER JOIN ProductApprover pa ON p.ProductId = pa.ProductId
WHERE p.ProductId = #id AND pa.Version = #version
Can anybody help me out please? Thank you kindly in advance.
Try this (I guess this is a LINQ interpretation of your SQL query):
int id = 123;
int version = 555;
var results = from p in context.Products
join pa in context.ProductApprovers
on p.ProductId = pa.ProductId
where p.ProductId equals id && pa.Version equals version
select new { Product = p, Approver = pa };
I suspect you want something like this:
var query = from product in db.Products
where product.ProductId == productId
select new {
Product = product,
Approvers = product.Approvers.Where(pa => pa.Version == version)
};
If that doesn't do what you want, could you explain where it falls down?
When getting a product collection in Magento, I would expect the StoreFilter to do just that, filter by the current store. But I can't get it to work.
Say I have 2 stores set up like so:
And both stores have a different root category. Main Store is the default sample data, Store2 has just one product I added. I would have thought that using the store filter, only products within the root category of the current store would show up. But I'm getting every product showing. I'm testing this by placing the following in my category view template:
$store_id = Mage::app()->getStore()->getId();
$_testproductCollection = Mage::getResourceModel('reports/product_collection')
->setStoreId($storeId)
->addStoreFilter($store_id)
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName());
};
If I echo the store ID, it's giving me the correct number. I have only one product in Store 2, so why am I getting every product from all stores returned? I can set every product in Main Store to not show in Store2 and then add a visibility filter, but that would take forever.
Also, I just noticed, if I echo the products store ID, I get the current ID, not the store it's assigned to:
echo $_testproduct->getStoreId()
What's going on?
UPDATE (April 8 2011):
OK, so I tried joining the fields so that the store_id is included (as suggested below), the section of code {{table}}.store_id = 1 is just setting all the products to have a store_id of 1. How can I just get the store_id associated with the product?
$_testproductCollection = Mage::getResourceModel('catalog/product_collection');
$_testproductCollection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$_testproductCollection->getSelect()->distinct(true);
$_testproductCollection->addAttributeToSelect('*')->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
echo "STORE IS ".$_testproduct->getData('store_id')."<br/>";
};
If I check the catalog_category_product_index table of my db, the store_id's are correct.
$_testproductCollection should look like this $_testproductCollection = Mage::getResourceModel('reports/product_collection')->addAttributeToSelect('*')->addStoreFilter().
If You print SELECT from that collection You will see that there ain't any store column, so addStoreFilter() can't apply WHERE.
You should use joinField() on Your collection and add store_id column from catalog_product_entity_varchar table.
EDIT
Sorry to keep You waiting ;)
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$collection->getSelect()->distinct(true);
This should do the trick, but just to be sure, please check if you're getting right products :)
This worked for me:
Mage::app()->setCurrentStore($storeId);
$productCollection = Mage::getModel('catalog/product')
->getCollection()
->addStoreFilter()
->addAttributeToSelect(array('sku','price'));
OK, I think this works, haven't tested too much but seems to have done the trick. You need to first get your stores root category id, then join some fields so you have access to the products "category_id", then filter using that:
$_rootcatID = Mage::app()->getStore()->getRootCategoryId();
$_testproductCollection = Mage::getResourceModel('catalog/product_collection')
->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left')
->addAttributeToFilter('category_id', array('in' => $_rootcatID))
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
};
I think
You don't need to do any joins as the magento's setStoreId() will work.
$collection = Mage::getModel("catalog/product")
->getCollection()
->setStoreId(1) //change store Id according your needs
->addAttributeToSelect(array('name','url','sku'))
->setPageSize(20);
This will get maximum 20 products from store id 1