1

I need to add write a php script to run from a cron job that will add two Magento Attribute values and store the result as a third attribute in the MySQL database.

Any help would be appreciated. I've attached a screen shot that hopefully clarifies things.

3
  • If you can provide an SQL example of what you're trying to do I will try and provide an answer. Commented Dec 2, 2011 at 21:04
  • I think there may be an error in your question. Your image says row with attribute 141 should have the value of the summation, but your textual description says that the row with attribute_id 145 should have it. Commented Dec 2, 2011 at 22:13
  • That's correct The line should be "Set the value from row attribute_id 141 entity_id W to Z" but I'm unable to edit my original post. Apparently I don't have enough points to post an image. Well I did but now I can't edit because of it. Commented Dec 2, 2011 at 23:38

2 Answers 2

2

Working directly in SQL when dealing with EAV models is hard. Save yourself the effort and use Magento's classes instead. A minimal cron script might look something like this:

<?php

require 'app/Mage.php';
umask(0);
Mage::app();

$products = Mage::getModel('catalog/product')->getCollection();
foreach ($products as $product) {
    $product->setSumValue(
        $product->getFirstValue() + $product->getSecondValue()
    )
    ->save();
}

Magento provides magic methods so you can use syntax like getFirstValue(), getSecondValue() and setSumValue() to refer to attributes named first_value, second_value and sum_value respectively. Use the names of your actual attributes instead of the numbers 141, etc.

Sign up to request clarification or add additional context in comments.

5 Comments

If your intention is to keep the third value up to date then it would be wise to work with Magento's framework and create a listener for save events. It would update the attribute whenever the others are updated, negating the need for a cron and avoiding the short period when they are out of sync.
That's exactly my intention. The value of "Attribute _id" 145 is set by a custom php script so I guess another option would be to add it to add it to the end of that script? I'm also just a little confused by your explanation of the attribute names. Am I correct that if the attributes are named 145 = "stock_in_hand", 146 = "stock_in_transit" and 141 = "tot_inventory" I would remove the underscores and use :- settotinventory( $product->getstockinhand() + $product->getstockintransit()
Or is it setTotInventory( $product->getStockInHand() + $product->getstockInTransit()
BTW I just realised you're the REAL Clockwork Geek Magento Extension Developer!! I'm honored!! :)
It's camel case so "tot_inventory" becomes setTotInventory. You were right second time. If "stock_in_hand" is being set in another script then that is the ideal time to update "tot_inventory" too.
0

I think this should do it, but I haven't tested it.

The basic procedure is to create a temporary table which contains the summed values for those entities you care about, then update the proper attribute rows with those values.

Note that php is not necessary here, only SQL. You may of course want to use php to issue the query.

UPDATE 
catalog_product_entity_decimal, 
(SELECT entity_id, SUM(value) AS summedvalue FROM catalog_product_entity_decimal as cped 
    WHERE attribute_id IN (145, 146)
    AND EXISTS (SELECT 1 FROM catalog_product_entity_decimal WHERE entity_id=cped.entity_id and attribute_id=141)
    GROUP BY entity_id 
) AS sums

SET catalog_product_entity_decimal.value = sums.summedvalue
WHERE catalog_product_entity_decimal.entity_id=sums.entity_id
    AND catalog_product_entity_decimal.attribute_id=141;

This builds an intermediate table sums that looks like this (based on data in table screenshot):

entity_id | summedvalue
1         | 12
2         | 0

If there's an entity_id without a row with an attribute_id=141, that entity_id won't have a row in this sums table--this is ensured by the EXISTS() condition.

Then we update the catalog_product_entity_decimal table (I'll abbreviate it CPED) by joining it with sums on the entity_id.

CPED.entity_id | CPED.attribute_id | sums.entity_id | sums.summedvalue
1              | 145               | 1              | 12
2              | 145               | 2              | 0

SET CPED.value = sums.summedvalue does the actual setting.

6 Comments

Thanks a bunch for that!! I think I'm understanding. But can you clarify "AND EXISTS (SELECT 1 FROM catalog_product_entity_decimal WHERE entity_id=cped.entity_id and attribute_id=141)" If I;m understanding this correctly then it will only update product 1 and not move on to product 2 etc.
This requires that entity_id the in sums pseudo-table have a row somewhere in catalog_product_entity_decimal table with an attribute_id=141. It's a filter. You could accomplish the same thing with a self inner join using that condition. (In fact there are few different SQL solutions.)
Is it clearer if I explain the required function like this FIND row ("attribute_id" = 141) SET ("temp_entity_id" = "entity_id") Find row ("attribute_id" = 145 AND "entity_id" = "temp_entity_id") SET ("stock_qty" = "Value") Find row ("attribute_id" = 146 AND "entity_id" = "temp_entity_id") SET ("backorder_qty" = "Value") SET ("offered_qty" = SUM ("stock_qty"+"backorder_qty")) Find row (("attribute_id" = 141) AND ("entity_id" = "temp_entity_id")) SET ("value" = "qty_offered") Clear ("temp_entity_id","stock_qty","backorder_qty","offered_qty") GOTO Next "attribute_id" = 141
That's essentially what this sql does. You're thinking too procedurally. I'll expand my answer to explain more thoroughly.
Awesome!! Thanks a bunch!! I'm getting the following error when I try to run it though. #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE attribute_id IN (145, 146) AND EXISTS (SELECT 1 FROM catalog_product_e' at line 4 I've had a look through the documentation on the error and nothing is standing out. Any Ideas?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.