I am overriding the Mage/Adminhtml/Sales/Order/Grid.php and adding some data to the prepareCollection. This is how I got the customer EAV Attribute campaign_id to be included in the collection, but it is kind of hacky. I was wondering if there was a better way.
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
foreach ($collection as &$object){
$customer = Mage::getModel('customer/customer')
->setId($object->getCustomerId())
->load();
$object->setCampaignId($customer->getCampaignId());
}
$this->setCollection($collection);
return parent::_prepareCollection();
}
You'll need to join the data from customer records onto the order collection before its loaded.
You can observe the collection before & after load events. For sales/order_grid_collection collection these events are sales_order_grid_collection_load_before and sales_order_grid_collection_load_after - you'll want to use the former. The collection can be accessed in your _before_load event observer via $observer->getOrderGridCollection().
protected function _prepareCollection() {
$collection = Mage::getResourceModel($this->_getCollectionClass());
$class = get_class($collection);
$attribute = Mage::getModel('eav/config')
->getAttribute('customer', 'campaign_id');
$attributeId = $attribute->getAttributeId();
$backendType = $attribute->getBackendType(); //probably varchar
$tableName = Mage::getSingleton('core/resource')
->getTableName('customer_entity_' . $backendType);
$collection->getSelect()
->joinLeft(array('v' => $tableName),
'main_table.customer_id = v.entity_id AND attribute_id = 153',
array('v.value', 'v.attribute_id'));
$this->setCollection($collection);
return parent::_prepareCollection();
}
Related
How to get a list of skus whiout using the looping in magento.
Example: I am using below code with my conditons.
$productsCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('sku');
Now I want to result as array('A001','A002'....) etc.
I don't want to iterate (loop) the product collection.
Please suggest.
If you want to retrieve the collection in that way, you will have to loop through the collection and retrieve the sku.
$skus = array();
foreach ($productsCollection as $product) {
$skus[] = $product->getSku();
}
If you don't want that, you can just use a simple query because the SKU is kept in the catalog_product_entity table.
$conn = Mage::getSingleton('core/resource')->getConnection('core_write');
$table = 'catalog_product_entity';
$q = "SELECT sku FROM {$table}";
$list = $conn->fetchOneFieldAll($q, 'sku');
Retrieve the read connection you should use ->getConnection('core_read') not ->getConnection('core_write'). Whole codes is below which runs faster.
$resource = Mage::getSingleton('core/resource');
$readConnection = $resource->getConnection('core_read');
$skus = $readConnection->fetchCol('SELECT sku FROM `catalog_product_entity`');
foreach ($skus as $sku) {
echo $sku;
}
In the Grid.php, I need to join customer/customer model with my custom model.
protected function _prepareCollection() {
$collection = Mage::getResourceModel('customer/customer_collection')->addNameToSelect();
$collection->getSelect()->join(
array('e' => 'event'), 'e.customer_id=main_table.entity_id', array('status')
);
$this->setCollection($collection);
return parent::_prepareCollection();
}
Basically I need to add some more information (in this example is status) to the collection. The event table contains the customer_id as reference to customer_entity.entity_id. How can I do this?
If there is any error you are getting you can share. Meanwhile try below updated code.
protected function _prepareCollection() {
$collection = Mage::getResourceModel('customer/customer_collection')->addNameToSelect();
$collection->getSelect()->join(
array('e' => 'event'), 'e.customer_id=main_table.entity_id', array('e.status') // added 'e.status' in stead of 'status'
);
$this->setCollection($collection);
return parent::_prepareCollection();
}
Hope will help!
I used this code to select all customer details
function getCustomers() {
/* Magento's Mage.php path
* Mage Enabler users may skip these lines
*/
require_once ("../mysite/app/Mage.php");
umask(0);
Mage::app("default");
/* Magento's Mage.php path */
/* Get customer model, run a query */
$collection = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToSelect('*');
$result = array();
foreach ($collection as $customer) {
$result[] = $customer->toArray();
}
return $result;
}
But i alos want to check a field value...
That is thre have a column 'usertypecurrent ' in eav_attribute table.....
I need to check its value is 0.
That means select all customer its usertype is 0...
How can i do this?
You can use addAttributeToFilter to filter results based on attribute values
$collection = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToFilter('usertypecurrent', array('eq' =>0))
->addAttributeToSelect('*');
Is it possible to filter a Magento collection using an array of id's BUT have the collection results ordered by the order of the id's passed to the filter.
For example:
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('entity_id', array(
'in' => array(1, 3, 2),
));
I would like the collection to have products in order, 1,3,2 so as when looping through the collection they come out in that specific order?
The only alternative i currently have is to manually create an array of products:
$productIds = array(1,3,2);
$collection = array();
foreach($productIds as $productId) {
$collection[] = Mage::getModel('catalog/product')->load($productId);
}
This obviously works but seems like an ugly way to do this.
is there a way to do this purely via magento collections?
$productIds = array(1,3,2);
/**
* Build up a case statement to ensure the order of ids is preserved
*/
$orderString = array('CASE e.entity_id');
foreach($productIds as $i => $productId) {
$orderString[] = 'WHEN '.$productId.' THEN '.$i;
}
$orderString[] = 'END';
$orderString = implode(' ', $orderString);
/**
* Filter the collection
*/
$productCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('entity_id', array('in' => $productIds));
/**
* Apply the order based on the case statement
*/
$productCollection->getSelect()
->order(new Zend_Db_Expr($orderString))
Pretty old but a simple solution I found on stackoverflow is
$productIds = array(1,3,2);
$products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('entity_id', array('in' => $productIds));
$products->getSelect()->order("find_in_set(entity_id,'".implode(',',$productIds)."')");
from here on stackoverflow
You can load the collection before sorting it in PHP. Eg :
$result = array();
$productIds = array(1,3,2);
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('entity_id', array('in' => $productIds))
->load();
foreach ($productIds as $productId) {
if ($product = $collection->getItemById($productId)) {
$result[$productId] = $product;
}
}
Else, purely with collections, you should first pass by the Zend_Db_Select object of the collection, to be able to sort on expressions (what may not be possible with eg EAV based collections and calls to addAttributeToSort or sortOrder).
Then you can either use multiple order calls as stated in Gershon's answer, or use a single order with a generated CASE WHEN THEN statement. Knowing that it could depend on the maximum number of IDs you may have to filter on.
This is a challenging question, here is a solution that should work:
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('entity_id', array(
'in' => array(1928, 1930, 1929),
))
->addAttributeToSort('entity_id = 1928', 'ASC')
->addAttributeToSort('entity_id = 1930', 'ASC')
->addAttributeToSort('entity_id = 1929', 'ASC')
;
There is this method getCategoryIds() in Mage_Catalog_Model_Resource_Eav_Mysql4_Product. This method returns all category IDs of requested product. I need to modify the SELECT statement so it will return also category names.
Here is the basic query:
$select = $this->_getReadAdapter()->select()
->from($this->_productCategoryTable, 'category_id')
->where('product_id=?', $product->getId());
I can't use catalog_category_flat table to for some reasons, so I have to use EAV tables. So at this point I have this query:
$select = $this->_getReadAdapter()->select()
->from($this->_productCategoryTable, 'category_id')
->where('catalog_category_product.product_id=?', $product->getId())
->join(
array('a' =>'catalog_category_entity_varchar'),
'a.entity_id = catalog_category_product.category_id',
array('name' => 'value')
)
->join(
array('b' => $this->getTable('eav/attribute')),
'b.attribute_id = a.attribute_id',
array()
)
->where("b.attribut_code = 'name'");
This works, but I'd like to ask if there is a better way of doing it.
Easiest and probably cleanest:
$categories = $product->getCategoryCollection()
->addAttributeToSelect('name');
Then you can simply traverse the collection:
foreach($categories as $category) {
var_dump($category->getName());
}
I found this post: Joining an EAV table and made the function, which will add the category join query, use it from the collection.
Just call this function from the code this way:
// To join the name of category
$this->joinCategoryAttribute('<your table alias>.category_id', 'name');
And this is the function:
public function joinCategoryAttribute($joinOriginId, $code)
{
$attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_category', $code);
$entityType = Mage::getModel('eav/entity_type')->loadByCode('catalog_category');
$attribute = Mage::getModel($entityType->getAttributeModel())->load($attributeId);
$entityTable = $this->getTable($entityType->getEntityTable());
$alias = 'table' . $code;
$table = $entityTable . '_' . $attribute->getBackendType();
$field = $alias . '.value';
$this->getSelect()
->joinLeft(array($alias => $table),
"{$joinOriginId} = {$alias}.entity_id AND {$alias}.attribute_id = " . $attribute->getAttributeId(),
array($attribute->getAttributeCode() => $field)
);
return $this;
}