Easy way to minify magento HTML output

Here is a quick way to minify Magento HTML output of your website

In magento root folder open lib/Zend/Controller/Response/Abstract.php  find out function outputBody  and replace  the code

$body = implode('', $this->_body);
echo $body

with

$body = implode('', $this->_body);
		$body = preg_replace('~>\s+<~', '><', $body);
        echo $body;

How to prevent unused css files loading on your magento e-commerce site header

Optimizing your page is most important to get quick page load and improve user experience. A good performance website will rank well in google.  However if you check your site in google page speed insight sometime you can see an error like ‘Optimize CSS Delivery of the following’.  You can inspect your css using google chrome inspect tool. Once click inspect, select Audit tab and run audit. You can see a result like below

chrome auditing

From above pictures some of css loaded in page 100% not used, we should prevent loading this page in site to reduce page size, http request and load other used content quickly.

Use below code:

Copy App/code/core/Mage/Page/Block/Html/Head.php
To
App/code/local/Mage/Page/Block/Html/Head.php

Find out function named &_prepareStaticAndSkinElements  and replace below code

 

 

foreach ($skinItems as $params => $rows) {
            foreach ($rows as $name) {
                $items[$params][] = $mergeCallback ? $designPackage->getFilename($name, array('_type' => 'skin'))
                    : $designPackage->getSkinUrl($name, array());
            }
        }

with

$path=$_SERVER['REQUEST_URI'];
        $actionName = $this->getAction()->getFullActionName();
        foreach ($skinItems as $params => $rows) {
            foreach ($rows as $name) {
                if($path=="/" && ($name=='css/widgets.css' || $name=='css/captions.css' || $name=='css/settings.css' || $name=='css/slider.css' || $name=='css/cloud-zoom.css' || $name=='css/sagePaySuite.css' || $name=='css/giftvoucher.css' || $name=='css/reupdate.css')): //for home page 
                    $name="";
                elseif($actionName=="catalog_category_view" && ($name=='css/widgets.css' || $name=='css/captions.css' || $name=='css/settings.css' || $name=='css/slider.css' || $name=='css/cloud-zoom.css' || $name=='css/giftvoucher.css' || $name=='css/reupdate.css' || $name=='css/jquery-ui-1.8.23.custom.css')): //for category page
                    $name="";
                elseif($actionName=="catalog_product_view" && ($name=='css/widgets.css' || $name=='css/captions.css' || $name=='css/settings.css' || $name=='css/calendar-win2k-1.css' || $name=='css/reupdate.css')): //for product details page
                    $name="";
                elseif($actionName=="checkout_cart_index" && ($name=='css/widgets.css' || $name=='css/captions.css' || $name=='css/settings.css')): //for cart page
                    $name="";
                elseif($actionName=="checkout_onepage_index" && ($name=='css/widgets.css' || $name=='css/captions.css' || $name=='css/settings.css' || $name=='css/cloud-zoom.css' || $name=='css/slider.css')): //for login page
                    $name="";
                endif;
                if($name!=""):
                $items[$params][] = $mergeCallback ? $designPackage->getFilename($name, array('_type' => 'skin'))
                    : $designPackage->getSkinUrl($name, array());
                endif;
            }
        }

change css file name as per your theme.

Good Luck.

Update stock in ChannelAdvisor after an item sold in Magento e-commerce site

Here is the php example for updating stock in Channel Advisor after an item sold in Magento site.

<?php
$order_id=15115; //this will be dynamic, u can use magento webservice or an extension to observe after sales 
update_ca_stock($order_id);
function update_ca_stock($order_id){
//taking order details using order id
$root=$_SERVER['DOCUMENT_ROOT'];
require_once $root.'/app/Mage.php';
Mage::app("default");
$order = Mage::getModel('sales/order')->loadByIncrementId($order_id);
 // get order details from magento
$orderValue = number_format ($order->getGrandTotal(), 2, '.' , $thousands_sep = '');
$orderItems = $order->getItemsCollection();
    $skuQtyArray = array();
	$skuDuplArray = array();
	$skuList=array();
	$i=0;
    foreach ($orderItems as $item)
    {
        $product_id = $item->product_id;
        $product_sku = $item->sku;
        $product_name = $item->getName();
        $product_qty = $item->getQtyOrdered();
        $_product = Mage::getModel('catalog/product')->load($product_id);
        $product = Mage::getModel('catalog/product')->loadByAttribute('sku', $product_sku);  
		//use this sectioon only if u have multiple distribution center in CA and its details u can get based on magento backend product attributes
		$location = trim(Mage::getModel('catalog/product')->load($product_id)->getAttributeText('stock_location'));
		if($location=="location" || $location==""):
			$location="CA Distribution center code";
		endif;
		//end distribution center list
        $productType=$product->getTypeID();  //choose SKU as per your store product configuration
        if($productType=='simple')
        {                                                                   
			 $text=explode(" ",$product_sku);
			 $product_sku=$text[0];
			  if(!in_array($product_sku,$skuDuplArray)):
			    $skuQtVal[$i]['sku'] = $product_sku;  //SKU - should match with SKU in CA
				$skuQtVal[$i]['qty']=$product_qty;    //Quantity need to update on CA 
				$skuQtVal[$i]['location']=$location;    //Distribution center code, which need to be added to update Quantity                 
				$skuDuplArray[]=  $product_sku;      //You may get some duplication SKU when u get order details from magento, I used this way to filter out duplicate SKU before do API call to CA
				$skuList['string'][$i]=$product_sku;  //SKU array for check all SKU exists in CA first before start stock update API call. If any SKU in array not exist in CA the API call will return error
				$i++;
			endif;	               
			
        }
		}
	// call custom php function to update CA stock after an item sold
	UpdateCAstock($skuList,$skuQtVal,$order_id);
}
function UpdateCAstock($skuList,$skuQtVal,$order_id){
$root=$_SERVER['DOCUMENT_ROOT'];
require_once($root.'/nusoap/lib/nusoap.php');
$client = new nusoap_client('https://api.channeladvisor.com/ChannelAdvisorAPI/v7/InventoryService.asmx?WSDL', true );
$err = $client->getError();
if ($err)
{
	//error log
}
$developerKey = '';
$password = '';
$headers = '<web:APICredentials>
				<web:DeveloperKey></web:DeveloperKey>
				<web:Password></web:Password>
		   </web:APICredentials>';
$arrData = array('accountID'=>'', 'skuList'=>$skuList);
$result = $client->call('GetInventoryItemList', $arrData, false, false, $headers); //call to get current quantity details in CA 
if($result['GetInventoryItemListResult']['Status']=='Failure'){ //if call failed
				//this section can help if the error is SKU not exists
				$messge=$result['GetInventoryItemListResult']['Message'];
				$fields=explode("Parameter name:",$messge);
				$notExitsSku = trim($fields[1]);
				if(count($skuList['string'])>0){
					$nonExistsSku[0]['SKU']=$notExitsSku;
					$nonExistsSku[0]['Quantity']=1;
					$nonExistsSku[0]['MessageCode']=1;
					$skuList=remove_element_by_value($skuList,$notExitsSku);   // remove non existing SKU
					UpdateCAstock($skuList,$skuQtVal,$order_id); //Call same function again after remove non exists SKU from array list
				}
}elseif ($client->fault)
{
	//error log
}
else
{
$err = $client->getError();
if ($err)
{
	//error log
}
else
{
	$result=$result['GetInventoryItemListResult']['ResultData']['InventoryItemResponse'];
	$i=0;
//This section will prepare Sku List array with quantity need to update on CA based on quatity sold and current stock in CA
if (count($skuList['string'])==1) //for single SKU 
{
		
		$search_result=searchArray($skuQtVal,$result['Sku']);
		$text=explode("+BH+",$search_result);
		$qty=$text[0];
		$location=$text[1];
		 if($qty==""):
			$qty=0;
		endif;
		$skulist['InventoryItemQuantityAndPrice'][$i]['Sku'] = $result['Sku'];
		$resultDc=$result['DistributionCenterList']['DistributionCenterInfoResponse'];
		$l=count($resultDc);
		if($resultDc[0]):
			if($resultDc[0]['DistributionCenterCode']==$location):
				$available_qty=$resultDc[0]['AvailableQuantity'];
			elseif($resultDc[1]['DistributionCenterCode']==$location):
				$available_qty=$resultDc[1]['AvailableQuantity'];
			endif;
		else:
			if($resultDc['DistributionCenterCode']==$location):
				$available_qty=$resultDc['AvailableQuantity'];
			elseif($resultDc['DistributionCenterCode']==$location):
				$available_qty=$resultDc['AvailableQuantity'];
			endif;
		endif;
		if($available_qty>=$qty):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = $available_qty-$qty;
		elseif($available_qty<=0):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = 0;
		elseif($qty>$available_qty):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = 0;
		endif;
		$skulist['InventoryItemQuantityAndPrice'][$i]['UpdateType'] = 'Available';
		$skulist['InventoryItemQuantityAndPrice'][$i]['DistributionCenterCode'] = $location;
}
else
{
 
  foreach($result as $res){  //if multiple SKU need to update
		//$qty=$skuQtVal[$i]['qty'];
		$search_result=searchArray($skuQtVal,$res['Sku']);
		$text=explode("+BH+",$search_result);
		$qty=$text[0];
		$location=$text[1];
		if($qty==""):
			$qty=0;
		endif;
		$skulist['InventoryItemQuantityAndPrice'][$i]['Sku'] = $res['Sku'];
		$skulist['InventoryItemQuantityAndPrice'][$i]['UpdateType'] = 'Available';
		$resultDc=$res['DistributionCenterList']['DistributionCenterInfoResponse'];
		$l=count($resultDc);
		if($resultDc[0]):
			if($resultDc[0]['DistributionCenterCode']==$location):
				$available_qty=$resultDc[0]['AvailableQuantity'];
			elseif($resultDc[1]['DistributionCenterCode']==$location):
				$available_qty=$resultDc[1]['AvailableQuantity'];
			endif;
		else:
			if($resultDc['DistributionCenterCode']==$location):
				$available_qty=$resultDc['AvailableQuantity'];
			elseif($resultDc['DistributionCenterCode']==$location):
				$available_qty=$resultDc['AvailableQuantity'];
			endif;
		endif;
		if($available_qty>=$qty):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = $available_qty-$qty;
		elseif($available_qty<=0):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = 0;
		elseif($qty>$available_qty):
			$skulist['InventoryItemQuantityAndPrice'][$i]['Quantity'] = 0;
		endif;
		$skulist['InventoryItemQuantityAndPrice'][$i]['DistributionCenterCode'] = $location;
		$i++;
	}
}
	$arrData = array('accountID'=>'', 'itemQuantityAndPriceList'=>$skulist);
// Call the SOAP method and send to CA API for update stock
	$result = $client->call('UpdateInventoryItemQuantityAndPriceList', $arrData, false, false, $headers);

		if ($client->fault)
			{
				
			}
			else
			{
			$err = $client->getError();
			if ($err)
			{
				
			}
			else
			{
				echo "Success"; //if call return success message
			}
			}
			
	//end
}
}


}
function remove_element_by_value($arr, $val) {
   $return = array(); 
   foreach($arr as $k => $v) {
      if(is_array($v)) {
         $return[$k] = remove_element_by_value($v, $val); //recursion
         continue;
      }
      if($v == $val) continue;
      $return[$k] = $v;
   }
   return $return;
}
function searchArray($skuQtVal,$sku){
		$sku_found=0;
		$l=count($skuQtVal);
		for($j=0;$j<=$l-1;$j++){
			if($skuQtVal[$j]['sku']==$sku):
				$sku_found=1;
				$qty=$skuQtVal[$j]['qty'];
				$location=$skuQtVal[$j]['location'];
				
				break;
			endif;
		
		}
		if($sku_found==1):
			return $qty."+BH+".$location;
		else:
			return 0;
		endif;
		
	}
	

?>

ChannelAdvisor GetOrderList Nusoap / PHP Example

I have  been working with Channel Advisor GetorderLisst API call to get order details between a specific date, below code will help you to get correct data from channeladvisor

require_once('nusoap.php');
$client = new nusoap_client('https://api.channeladvisor.com/ChannelAdvisorAPI/v7/OrderService.asmx?WSDL', true );
$client->namespaces = array(
  'soapenv'=>"http://schemas.xmlsoap.org/soap/envelope/",
  'web'=>"http://api.channeladvisor.com/webservices/",
  'ord'=>"http://api.channeladvisor.com/datacontracts/orders"
); 
$err = $client->getError();
if ($err)
{
//echo 'Constructor error' . $err . '';
}
$accountID='';
$headers = '<web:APICredentials>
<web:DeveloperKey>your key</web:DeveloperKey>
<web:Password>your password</web:Password></web:APICredentials>';
$bodyxml = '<web:GetOrderList>
<web:accountID>your account id</web:accountID>
<web:orderCriteria>
<ord:OrderCreationFilterBeginTimeGMT>2016-02-10T00:00:00</ord:OrderCreationFilterBeginTimeGMT>
  <ord:OrderCreationFilterEndTimeGMT>2016-02-11T00:00:00</ord:OrderCreationFilterEndTimeGMT>
<ord:DetailLevel>Complete</ord:DetailLevel>
</web:orderCriteria>
</web:GetOrderList>';
$result = $client->call('GetOrderList', $bodyxml, false, false,$headers);
//Print out the results
print_r($result);

Features of PHP7

We all know that PHP keeps evolving. Every new major release there are new features. We Still do not know the whole features of PHP7 because the whole features is not described yet. PHP 7 was led by Zend to speed up the PHP applications, is based on the PHPNG (PHP Next-Gen) project. Since PHPNG is an open sourced and now mingle with PHP 7, its performance becomes more than doubled.

Now we can describe about some of the top  features of PHP7 that is already implemented. Here we are going to discuss about the 5 top features of PHP7.s

Performance Improvements

The main goal of PHPNG was to bring performance improvements in the application such as WordPress, Drupal or SugarCRM. The main basis of the PHP7 is the improved codebase, importantly it reduces memory consumption.

The biggest feature of PHP 7 is the performance improvements due to major work on its Zend Engine, which will be Zend Engine 3 with PHP 7. The Performance Improvements is happening in PHP7 with the addition of PHPNG engine.

JIT Engine (Just In Time compilation)

The development of PHPNG was started with the inspiration to research the execution of a JIT Engine for the Zend Engine based PHP. The JIT engine can dynamically compile Zend opcodes into a native machine code that eventually would make the code run faster next time it is run.

While the JIT engine implementation is not yet built-in the PHPNG branch, but it is definitely in the plans of Zend to allow bringing a JIT engine to PHP 7.

AST: Abstract Syntax Tree

The another main feature of PHP7 is the implementation of the AST (Abstract Syntax Tree), It is not the first time Nikita Popov proposed the implementation, He has already proposed the Abstract Syntax Tree as an intermediary step for the PHP compilation process in 2012.

He described the several advantages of AST in his proposals, the main advantage of AST is its potential for more optimizations that would make PHP run even faster and now In the latest proposal he describes the possibility to expose the AST to PHP extensions and userland applications. That could open space for more interesting tools like static code analyzers which are often useful to detect bugs or potential source level optimizations of your PHP code.

Asynchronous Programming

Julien Pauli, one of the maintainers of the latest PHP releases, has been commenting about refactoring PHP I/O multiplexing layer. That is some changes in the code that takes care of handling events related to accesses to files, network, databases, timers, etc.

Simply we can say that asynchronous programming would allow future PHP version to easily implement support to the execution of parallel tasks within the same request, hence the performance of the PHP improved completely to another stage

To get the support for asynchronous programming, New PHP code needs to be written for taking the  advantage of the asynchronous programming potential. It doesn’t mean that  asynchronous programming built-in support will be enabled in PHP 7.

Standalone Multi-threading Web Server

By the standalone multi-threading webserver PHP would become more scalable. Already PHP can run from the multi-threaded web servers like ngynx, lighttpd or even Apache in worker mode. But it is much better for having PHP run on its own multi-threading web server. With the help of a single memory pool a multi-threading web server can handle many simultaneous requests by avoiding the memory waste when you run PHP as FastCGI or in Apache pre-fork mode.

This Standalone Multi-threading Web Server allow PHP to use a single pool of database connections, it helps during access peaks by minimizing the number of simultaneous database connections

In the making plan of PHP 7, standalone multi-threading Web server is not yet in the plans but it is good to have this multi-threading Web server in PHP 7.

Spaceship Comparison Operator

In PHP 7, they are going to introduce a new operator <=> for combined comparison. This operator is quite similar to these functions, strcmp() or version_compare(). These upcoming Spaceship Comparison Operator is mostly used when dealing with sorting and can be used for all generic PHP values with the same semantics as <, <=, ==, >=, >.

Return Type Declaration & Scalar Type Hints

Finally PHP gets return types, In PHP 7 we will able to indicate proper return types on functions in the form of:

function foo(): array {

return [];

}

In addition, new scalar type hints are supported by the argument type hints and the new return-type declarations, it allows the developers to denote that they are awaiting strings, int, bools, etc.

 

[box]PHP 7 Releasing ScheduleThe releasing date of PHP is not yet declared but we can assume that the PHP 7.0 would release in late 2015. According to the PHP timeline they aims to release PHP 7 in October 2015. Even the releasing date may be delayed, it doesn’t go much far. The releasing will be before the end of the year.[/box]

 

 

 

Magento PHP Script to export products data into CSV

If you ever had an issue with exporting complete products from Magento Backend due to memory allocation error or script time out error? especially if you are using a shared server.

Below PHP script can help you to export complete data into CSV format.

<?php
	ini_set('memory_limit','2048M');
	ini_set('max_execution_time',3600); 
    require_once "../app/Mage.php";
	Mage::app("default");
	$_helper = Mage::helper('catalog/output');
	$helper = Mage::helper('shoppersettings/image');
	$imgX = 252;
	$imgY = $helper->calculateHeight($imgX);
	$filename = 'export_all_products.csv'; //output will write on this file and save into your directory where this code upload and run
//on below line specify your attribute name need to export. It may be different from below. This will export all products simple and configurable
	$_productCollection = Mage::getModel("catalog/product")->getCollection()->addAttributeToSelect(array('name', 'price','special_price','brand','color','size','lingerie_type', 'image', 'status','short_description','description','sku'));
	//->setCurPage(7)   //set paging
  	//->setPageSize(5000); //set number of records you want to export
	$file = fopen($filename, 'w');     
	foreach ($_productCollection as $_product):
   		$name= $_product->getName();
		$name=str_replace("&","&amp;",$name);
		$sku=$_product->getSku();
		$text=explode(" ",$sku);
		$sku=$text[0];
		$url_key=$_product->getProductUrl();
		$image_url=Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getImage());  // get correct image path, not from cache
		if($_product->getSpecialPrice()!=""):
			$price=number_format($_product->getSpecialPrice());
		else:
			$price=number_format($_product->getPrice());
		endif;
		$desc=strip_tags($_product->getShortDescription());
		$desc=str_replace("&nbsp;"," ",$desc);
		$desc=str_replace("&","&amp;",$desc);
		$desc1=strip_tags($_product->getDescription());
		$desc1=str_replace("&nbsp;"," ",$desc1);
		$desc1=str_replace("&","&amp;",$desc1);
		$id=$_product->getId();
                //get parent id of a child product
		$parent_ids = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($_product->getId());
$parent_collection = Mage::getResourceModel('catalog/product_collection')
    ->addFieldToFilter('entity_id', array('in'=>$parent_ids))
    ->addAttributeToSelect('sku','entity_id');
$parent_skus = $parent_collection->getColumnValues('sku');
$entity_ids = $parent_collection->getColumnValues('entity_id');
		if($parent_skus[0]!=""):
			$parent_sku=$parent_skus[0];
			$pSku=$parent_skus[0];
			$pId=$entity_ids[0];
			$brand = Mage::getModel('catalog/product')->load($pId)->getAttributeText('brand');
			$url_key = Mage::getModel('catalog/product')->load($pId)->getProductUrl();
			$brand=str_replace("&","&amp;",$brand);
			$image_url=Mage::getModel('catalog/product')->load($pId)->getImageUrl();
			$lingerie_type = Mage::getModel('catalog/product')->load($pId)->getAttributeText('lingerie_type');
			$lingerie_type=str_replace("&","&amp;",$lingerie_type);
		else:
			$pSku="";
			$brand="";
			$lingerie_type="Lingerie";
		endif;
		$color=$_product->getAttributeText('color');
		$size=$_product->getAttributeText('size');
		$qty=5;
		$availability="In stock";
		$category="Apparel &amp; Accessories &gt; Clothing";
      $data[] = array($id,$sku,$name,$url_key,$image_url,$price,$desc,$desc1,$pSku,$brand,$lingerie_type,$color,$size,$availability,$qty,$category);   
	   endforeach;           
      fputcsv($file, array('ID','SKU', 'Name', 'URL Key','Image','Price','Short Description','Description','Parent SKU','Brand','Lingerie Type','Color','Size','Availability','Quantity','Category'));      
   foreach($data as $row){
	   fputcsv($file, $row);      
   }
   echo "Done";
	?>