Magento Collection Query - magento

I created new customer attribute 'personal_number' and now want to show it in new column in adminhtml sales_order_grid.
I've done all stuff to show column in grid (class rewrite in config.xml), created MyName_MyModule_Block_Adminhtml_Order_Grid where need to rewrite _getCollectionClass() and _prepareColumns(). My problem is in _getCollectionClass() where I need to do database query to join customers attribute data to orders collection. Becouse I'am very new in Magento, logic of magento-way queries for me is very hard to follow. Can someone help me to write MySql query below in Magento-way to get value of my customer attribute 'personal_number' in orders grid:
SELECT Orders.*, Customers.customer_id, Custumer.personal_namber FROM Orders INNER JOIN Customers ON Orders.customer_id = Customer.customer_id

You usually don't need to change _getCollectionClass, but rather do the join on the grid, on _prepareCollection. Ie:
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
//we changed mysql query, we added inner join to order item table
$collection->join(
// Alias => Table name
array('customers' => "customer/customer"),
// Join condition
'main_table.customer_id = customer.customer_id',
// Fields to select
array('personal_number'=>'personal_number');
$this->setCollection($collection);
return parent::_prepareCollection();
}
Taken from here, have a look at the full article for more help: http://inchoo.net/magento/how-to-extend-magento-order-grid/

Related

WinterCMS/ OctoberCMS builder - sorting product in categories

I built the plugin (with builder) where I have products and categories. Product and categories are "conected" by relation table. I have list of products and another list of categories. On page where I list my all categories everthing works fine. The problem is with the single category view. Now products in a single category are listed by add order. But I want to have my own order of products or some sort of reordering. Builder delivers sorting in record list (categories page) but not in record details (single category page).
Thanks for answers.
In your model, you have already added relationship like category <-> products
Here you can add an order option to set the order.
// inside category model
public $hasMany = [
'products' => [
\Acme\Shop\Models\Product::class,
'order' => 'title desc', // <- here although its hardcoded
]
];
Or if you prefer dynamic order then inside your page code section you can add the onStart function and fetch the product manually.
function onStart() {
$id = 1; // just for example you can get category based on slug
$sortedProducts = Category::find($id)
->products()->orderBy('title')->get();
// dynamic as per your need ^
$this['products'] = $sortedProducts;
}
// now in the code section you can use `products` and they will be sorted
if any doubt please comment

Laravel HasManyThrough CrossDatabaseRelation

strange question:
I have 3 Models
Order
with id as PK
Orderline
with id as PK and order_id as FK. brand and partnumber are two separatet colums
Article
with combined PK brand and partnumber
**which is on another database **
One Order hasMany Orderlines. Every Orderline hasOneArticle.
i had make a function within order:
public function articles()
{
$foreignKeys = [
'brand_id',
'article_number',
];
$localKeys = [
'brand',
'partnumber',
];
return $this->hasManyThrough('App\Models\Masterdata\Articles','App\Models\Oms\OrderLine',$foreignKeys,$localKeys,'id','id');
}
How can i retrieve all Attributes from articles through Order?
I tried something like this:
$order = Order::find($orderid)->articles();
dd($order);
//did not work
$order = Order::with('orderlines.articles')->where('id','=',$orderid)->get();
Do you have an idea for me?
You can configure more than one database in the database.php config, and specify the $connection name in the Model class.
For the most part, Eloquent doesn't do JOINs, it just does IN statements on the key values from the preceding query, and programmatically marries the results together after the fact. Partly to avoid the mess of keeping table aliases unique, and partly to offer this kind of support- that your relations don't need to live in the same database.
In other words, what you have there should work just fine. If there's a specific error getting thrown back though, please add it to your post.

Entity Framework & Linq Orderby

We have a 3 table relationship in an MVC application that is using the EF6. For example a Customer Table related to an Orders Table(the many side) and the Orders Table is related to an OrderItems Table (the many side).
We would like in ONE TRIP to the database get all the records for all tables and be able to order each table.
We know we can use the include extension like context.Customers.Include("Orders.OrderItems") to eagerly load all data. But we keep getting errors when we try to order each table.
For example we would like to order the Customer Table by CustomerId column, and the Orders Table by Date column and the OrderItems by ProductId column.
Any assistance would be apreciated
If you have navigation properties from OrderItem to Order and from Order to Customer, then you can get ordered `OrderItems' you can achieve this like:
var orderItems = context.OrderItems
// Filter if needed with .When
.Include(m => m.Order.Customer)
.OrderBy(m => m.Order.Customer.CustomerId)
.ThenBy(m => m.Order.Date)
.ThenBy(m => m.ProducetId)
.ToList();
But, if you want to get customers, what you can do is load ordered customers like:
var customers = context.Custoemr
.Include(m => m.Orders.Select(o => o.OrderItem))
.OrderBy(m => m.CustomerId)
.ToList();
Then order Order and OrderItem. As you have loaded all data, ordering collections will not make any database call, and it will remain one-trip to database:
foreach(Customer customer in customers)
{
customer.Orders = customer.Orders.OrderBy(m => m.Date);
foreach (Order order in customer.Orders)
{
order.OrderItems = order.OrderItems.OrderBy(m => m.ProducetId);
}
}

Replace the column name in the magento collection while loading it

I have a custom module and I am loading a collection like following
$collection = Mage::getModel('module/product')->getCollection()
->addFieldToFilter('sku',$sku);
There is field named as prod_id in the database. Can I get this as entity_id while loading the collection?
If yes. Please help how to do this.
First of all all
addAttributeToFilter() is used to filter EAV collections.
addFieldToFilter() is used to filter Non-EAV collections.
EAV-models are for example product, customer, sales, etc so you can use use addAttributeToFilter() for those entities.
addFieldToFilter() is mapped to `addAttributeToFilter()` for `EAV` entities. So you can just use `addFieldToFiler().`
You can have a look in app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php where the Mapping is done:
public function addFieldToFilter($attribute, $condition = null) {
return $this->addAttributeToFilter($attribute, $condition);
}
If you are using custom module then you can directly use addFieldToFilter() with your column name
Like
$collection = Mage::getModel('module/model')->getCollection()
->addFieldToFilter('column_name',$data);
Let me know if you have any query

How to select from magento EAV tables when flat catalog product data is on

I have this code for selecting best selling products from Magento:
$productCollection = Mage::getResourceModel('reports/product_collection')
->addOrderedQty($startTime, $currentTime)
->addAttributeToSelect('*')
->setStoreId($storeId)
->addStoreFilter($storeId)
->setOrder('ordered_qty', 'desc')
->setPageSize($this->limit());
}
and it works fine, until I set "use flat catalog product" in backend to yes.
Is there any way to tell magento to not use flat tables, and use EAV instead?
Can any one help me with this.
Create a new model class ('mycatalog/product') that extends the original product class but hard code it to use the EAV resource model and EAV resource collection, and then use that model in your query code.
I'd been running my code from a stand alone php file, as soon as i moved my code into an admin module it stopped using the flat_file and went back to eav.
If you look at: Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
There's a method:
public function isEnabledFlat()
{
if (Mage::app()->getStore()->isAdmin()) {
return false;
}
if (!isset($this->_flatEnabled[$this->getStoreId()])) {
$this->_flatEnabled[$this->getStoreId()] = $this->getFlatHelper()
->isEnabled($this->getStoreId());
}
return $this->_flatEnabled[$this->getStoreId()];
}
You could modify this to add an extra condition that returns false based on your own criteria.
BTW, The reports collection mentioned in the first post by Blazo is an extension of this collection.
To expand on Alan's answer:
class Namespace_Module_Model_Category extends Mage_Catalog_Model_Category
{
protected function _construct()
{
$this->_init('catalog/category');
}
}
The above removes the check to see if flat was enabled and only inits the standard eav verson of the catalog/category resource.
And then when you wish to load your model ensuring that you get the eav model regardless of wither the flat data is enabled:
$category = Mage::getModel('namespace_module/category')->load($id)
I have use
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
before
Mage::getModel('catalog/product')->getCollection()
And it start fetching data from eav based system.
This is an old post but I thought one important point was not stated.
1. Once you set flat catalog to on you need to run indexer via cron or via admin/shell so that flat catalog tables get populated.
If you do have many products in your search bypassing flat catalog table will slow down your site and each search code will consume lots of resources.
I found that the easiest solution was to turn off the flat tables and then get the SQL query that magento executes using the ->load(true) parameter
e.g.
$collection = Mage::getModel('catalog/category')->getCollection();
$collection
->setStoreId($store->getId())
->addAttributeToSelect('*')
->addAttributeToFilter(array(array('attribute'=>'ig_unifeed_ids', 'like'=>"%:".$this->getId().":%")))
->load(true);
then turn flat tables back on and replace this code with:
$resource = Mage::getSingleton('core/resource');
$readConnection = $resource->getConnection('core_read');
$query = "SELECT `e`.*, `at_ig_unifeed_ids`.`value` AS `ig_unifeed_ids` FROM `catalog_category_entity` AS `e` INNER JOIN `catalog_category_entity_varchar` AS `at_ig_unifeed_ids` ON (`at_ig_unifeed_ids`.`entity_id` = `e`.`entity_id`) AND (`at_ig_unifeed_ids`.`attribute_id` = '139') AND (`at_ig_unifeed_ids`.`store_id` = 0) WHERE (`e`.`entity_type_id` = '3') AND ((at_ig_unifeed_ids.value LIKE '%:".$this->getId().":%'))";
$collection = $readConnection->fetchAll($query);
From this point on you will probably need to change other code like replacing
$category->getId()
with
$category["entity_id"]
I hope this helps a bit...
NOTE: this is a real solution for the IG_Unifeed module magento bug that disregards category filtering when using flat tables.

Resources