Magento 1 Categories, with and without Flat Tables

Sometimes Magento leaves you wondering, “WHY!?!?!?!?!?”

 

If flat categories are enabled, and you want all the children of a parent category, do this:

$children = Mage::getModel('catalog/category')->load($theCategoryIdHere)->getChildrenCategories();

If they are not enabled, do this:

$children = Mage::getModel('catalog/category')->getCategories($theCategoryIdHere);

How do you know if they are enabled?

if (Mage::helper('catalog/category_flat')->isEnabled()) {}

Also, getChildrenCategories() on the flat category list returns the category objects in the same order you find them in the admin category manager. However,

Mage::getModel('catalog/category')->load($theCategoryIdHere)->getChildren();

returns a comma separated string of child category ids in numerical order.

Magento 1 Data Upgrade Script: Set All Simple Products to Manage Stock

<?php
/* @var $installer Mage_Core_Model_Resource_Setup */
$installer = $this;
$installer->startSetup();

$collection = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect('*')
    ->addAttributeToFilter('type_id', 'simple');

foreach ($collection as $product) {
    $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId());
    $stockItem->setData('manage_stock', 1);
    $stockItem->setData('use_config_manage_stock', 1);
    $stockItem->save();
}

$installer->endSetup();

?>

SCP

You can do this with the scp command, which uses the ssh protocol to copy files across machines. It extends the syntax of cp to allow references to other systems:

scp username1@hostname1:/path/to/file username2@hostname2:/path/to/other/file

Copy something from this machine to some other machine:

scp /path/to/local/file username@hostname:/path/to/remote/file

Copy something from another machine to this machine:

scp username@hostname:/path/to/remote/file /path/to/local/file

Copy with a port number specified:

scp -P 1234 username@hostname:/path/to/remote/file /path/to/local/file

Finding the my.cnf Which Is Actually Loaded

sudo dtruss mysqld 2>&1|grep my.cnf

/usr/local/mysql/data$ sudo dtruss mysqld 2>&1 | grep my.cnf
Password:

stat64("/etc/my.cnf\0", 0x7FFF5548E548, 0x7FFF5548F300)		 = -1 Err#2
stat64("/etc/mysql/my.cnf\0", 0x7FFF5548E5dtrace: error on enabled probe ID 2135 (ID 940: syscall::read_nocancel:return): invalid kernel access in action #12 at DIF offset 92
stat64("/usr/local/mysql/etc/my.cnf\0", 0x7FFF5548E548, 0x7FFF5548F300)		 = 0 0
open_nocancel("/usr/local/mysql/etc/my.cnf\0", 0x0, 0x1B6)		 = 3 0
stat64("/Users/jennifer/.my.cnf\0", 0x7FFF5548E548, 0x1000)		 = -1 Err#2

open_nocancel("/usr/local/mysql/etc/my.cnf\0", 0x0, 0x1B6) = 3 0
is the line to look for

php-fpm, nginx, bad hoodoo magic, and the dreaded 502 gateway error on magento sites

When segmentation faults collide ….

If anything disrupts nginx’s ability to talk to php-fpm, you’ll see the 502 gateway error. Sometimes, that’s because the server guys did something. Sometimes, that’s because the dev guys did something. Sometimes, it’s really, really, really hard to tell.

If your host assures you it’s your code, and they are positive they have not updated anything on the server (php version, nginx version, anything at all), and more importantly, if the 502 gateway is intermittent and always worse under load, you need to consider your code. It may function, but function so poorly it kills the server.

On Magento sites, look for long running queries. You can stack trace by enabling the zend logger in lib/Varien/Db/Adapter/Pdo/Mysql.php.

One of the biggest coding mistakes in Magento customizations is inefficient queries. Running SQL queries inside a loop, for example, can really put a drain on your server. A long running query can consume so much memory it crashes php-fpm which times out the response from nginx and gives you a 502 gateway error, even though your server is running just fine as far as you can see.

Running SQL queries is a very expensive operation, and doing it in a loop tends to make it even worse. Instead of doing that we should use data collections to load models and then process the items in the collection.

Instead of:

foreach ($this->getProductIds() as $productId){
    $product = Mage::getModel('catalog/product')->load($productId);
    $this->processProduct($product);
}

Do this:

$collection = Mage:getResourceModel('catalog/product_collection')
    ->addFieldsToFilter('entity_id', array($this->getProductIds()))
    ->addAttributeToSelect(array('name'));

foreach ($collection as $product){
    $this->processProduct($product);
}

Especially be on the lookout for queries run through an adapter. Method fetchAll() used to fetch and iterate over larger result sets will lead to a very long execution time (again, with the memory thing and the time out thing and the 502 gateway thing). The better solution is to fetch the results row by row using the fetch() method.

Assuming you declared/initialized your adapter already, instead of this:

$rowSet = $adapter->fetchAll($select);
foreach ($rowSet as $row) {
    //process row
}

Do this:

$query = $adapter()->query($select);

while ($row = $query->fetch()) {
    //process row
}