Magento – Web Service Calls / API

At Fluid Branding we recently moved our website over to Magento. This all went very successfully, so one of the things we’re doing now is integrating our back office systems with Magento:

Fluid Branding Website - May 2012
Fluid Branding Website – May 2012

The first thing I needed to do was to retrieve details of a specified product from Magento. The back office system is on a different server from the website itself, so I needed to set up an API to be able to get the data. A simplified version of the API code that I set up follows, this code being present on the Magento server and the call being made using Curl from the back office system:

<?php

try {
	$root = $_SERVER['DOCUMENT_ROOT'];
	require_once $root.'/app/Mage.php';
	Mage::app('default');

	$params = $_REQUEST;

	$sku = (isset($params['sku']) ? $params['sku'] : FALSE);

	$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);

	$data = $product->getData();

	$attributeObj = $product->getResource()->getAttribute("manufacturer");
	$data['manufacturer_name'] = $attributeObj->getSource()->getOptionText($data['manufacturer']);

	$attributeObj = $product->getResource()->getAttribute("color");
	$data['color_name'] = $attributeObj->getSource()->getOptionText($data['color']);

	$attributeObj = $product->getResource()->getAttribute("option");
	$data['option_name'] = $attributeObj->getSource()->getOptionText($data['option']);

	$response['data'] = json_encode($data);
	$response['msg'] = 'Call completed successfully.';
	$response['success'] = TRUE;

} catch (Exception $e) {

	$response['data'] = '';
	$response['msg'] = $e->getMessage();
	$response['success'] = FALSE;

}

echo json_encode($response);

?>

As you can see, the data is returned in JSON format, which is then just de-coded on the client side. One thing to note in this example are the following chunks of code:

$attributeObj = $product->getResource()->getAttribute("manufacturer");
$data['manufacturer_name'] = $attributeObj->getSource()->getOptionText($data['manufacturer']);

…which, in the example above, is used to obtain the name of the manufacturer rather than just its id. I later found that a simpler way to do this is to use the following code:

$data['manufacturer_name'] = $product->getAttributeText('manufacturer');

Having set up this API I then found out that Magento had its own API system. Given that I needed to do another API call to search for some products and then return their details, I thought I’d try using Magento’s API system. The code that follows shows a test that I set up to do this and it demonstrates a few things beyond the simple examples given in the Magento documentation:

  • Searching for products using a ‘complex’ filter
  • Retrieving additional and custom product data attributes
  • Retrieving the option name for a dropdown field (manufacturer name in this case)
  • Retrieving main product image

Note that to get all the info I needed I had to call the following APIs:

  • catalogProductList
  • catalogProductInfo
  • catalogProductAttributeOptions
  • catalogProductAttributeMediaList
  • catalogProductAttributeList
<?php

try {

	$api = new SoapClient('http://www.fluidbranding.com/api/v2_soap?wsdl=1');

	$sessionId = $api->login('xxxxxxx', 'xxxxxxxxx');

	$filter = array('complex_filter' => array(
	            array('key' => 'name', 'value' => array('key' => 'like', 'value' => '%bags%'))
	        ));

	$products = $api->catalogProductList($sessionId, $filter);

	$attributes = new stdclass();
	$attributes->additional_attributes = array('name', 'manufacturer', 'supplier_prod_ref');

	$manufacturerAttrId = FALSE;
	$manufacturers = FALSE;
	foreach ($products as $product) {
		$productInfo = $api->catalogProductInfo($sessionId, $product->sku, null, $attributes, 'sku');
		$productInfo->attribute_details = getAttributes($productInfo->additional_attributes);
		if (!$manufacturerAttrId) {
			$manufacturerAttrId = getManufacturerAttrId($api, $sessionId, $productInfo->set);
			$manufacturers = $api->catalogProductAttributeOptions($sessionId, $manufacturerAttrId);
		}
		if ($manufacturers) {
			$productInfo->attribute_details->manufacturer_name = getManufacturerName($manufacturers, $productInfo->attribute_details->manufacturer);
		}
		$image = $api->catalogProductAttributeMediaList($sessionId, $productInfo->sku, null, 'sku');
		if ($image && isset($image[0])) {
			$productInfo->image_url = $image[0]->url;
		} else {
			$productInfo->image_url = '';
		}
	}

} catch (Exception $e) {

	var_dump(htmlspecialchars($api->__getLastResponse()));

}

if ($api) {
	$api->endSession($sessionId);
}

function getManufacturerAttrId ($api, $sessionId, $setId) {
	$attributes = $api->catalogProductAttributeList($sessionId, $setId);
	foreach ($attributes as $attribute) {
		if ($attribute->code == 'manufacturer') {
			return $attribute->attribute_id;
		}
	}
	return FALSE;
} 

function getAttributes ($attributes) {
	$attrDetails = new stdClass();
	foreach ($attributes as $attribute) {
		$key = $attribute->key;
		$attrDetails->$key = $attribute->value;
	}
	return $attrDetails;
}

function getManufacturerName ($manufacturers, $manufacturerId) {
	foreach ($manufacturers as $manufacturer) {
		if ($manufacturer->value == $manufacturerId) {
			return $manufacturer->label;
		}
	}
	return FALSE;
}
?>

 

What I found in my case is that the API calls just took too long (I think it was around 10 seconds to get details on around 30 products that met the search criteria!). I therefore ended up coding my own API which did the same thing in a fraction of a second.

I’d be interested in hearing about other people’s experiences with Magento API and how you’ve approached similar requirements.