Friday, August 12, 2016

How to Show All Magento Products Externally in PHP

In our previous article, we have seen how to display all the Magento orders externally (Not within Magento itself) in php.

Now, let's see a piece of code which applies same logic and show all products. Let's check out the code.

<?php
require_once 'app/Mage.php';
umask(0);
Mage::app();
// SEARCH MODE
if($_GET['q'] && trim($_GET['q']) !="")
{
    $collection =                                                                Mage::getResourceModel('catalog/product_collection')
             ->addAttributeToSelect('*')
            ->addAttributeToFilter( 
              array(
array('attribute'=> 'name',
      'like' => '%'.trim($_GET['q']).'%'
                     ),
array('attribute'=> 'sku',
                   'like' => '%'.trim($_GET['q']).'%'
                     ),
    ))
             ->load();
}
else
/// Normal Procedure
{
   $collection = Mage::getModel('catalog/product')
                ->getCollection()
                ->addAttributeToSelect('*')
->addAttributeToSort('name', 'ASC')
->load();
}
?>

The above code includes the Search handling part also. The condition if($_GET['q'] && trim($_GET['q']) !="") evaluates to true when user enters some keyword and hits Search button.

->addAttributeToFilter( array(
array('attribute'=> 'name',
      'like' => '%'.trim($_GET['q']).'%'
                      ),
array('attribute'=> 'sku',
      'like' => '%'.trim($_GET['q']).'%'
                      ),
))

Here, the addAttributeToFilter() generates an SQL like this

WHERE 'name' LIKE '%search%' OR 'sku' LIKE '%search%'

Next, we just need to iterate through the product collection $collection.

<table width="100%" border="0">
  <tr>
  <td colspan="5" align="center">
   <div>
    <form method="get">
      <input type="text" value="<?php echo $_GET['q'];?>" name="q">
      <button title="Search" type="submit">Search</button>
    </form>
   </div>
  </td>
  </tr>
  <tr class="header">
    <th width=""><strong>ID</strong></th>
    <th width=""><strong>Name</strong></th>
    <th width=""><strong>SKU</strong></th>
    <th width=""><strong>Price</strong></th>
    <th width=""><strong>Final Price</strong></th>
  </tr>
 <?php 
  // LOOP the Collection
  foreach ($collection as $_product)
  {
    $productID = $_product->getId();
    $_product  = Mage::getModel('catalog/product')
                  ->load($productID);
    $productPosition = 0;

    // Product is Enabled and VISIBILITY = Search, Catalog 
    if($_product->getStatus()==1 && $_product->getVisibility()==4)
    {
       // GET FINAL PRICE aftyer applying RULE
       $finalPrice = Mage::getModel('catalogrule/rule')
                     ->calcProductPriceRule( $_product, 
                      $_product->getPrice() );
       $_specialPrice = $_product->getFinalPrice();
       if($_specialPrice<=$finalPrice)
       {
 $finalPrice = $_specialPrice;
       }
       if($finalPrice)
       {
 $finalPrice = Mage::helper('core')->currency( 
                           $finalPrice, true, false);
       }
       else
       {
  $finalPrice = Mage::helper('core')->currency(
                 $_product->getFinalPrice(), true, false);
       }

       echo "<tr>";
       echo "<td>".$productID."</td>";
       echo "<td><a href='" . 
             $_product->getProductUrl() .
            "'>" . $_product->getName() .                                            "</a></td>";
       echo "<td>".$_product->getSku()."</td>";
       echo "<td>".Mage::helper('core')->currency( 
                 $_product->getPrice(), true, false).                                    "</td>";
       echo "<td>".$finalPrice."</td>";
       echo "</tr>";

    }
 }
?>
</table>

We are showing all the products which have Visibility 4 (i.e "Catalog, Search"). Also the product's final price is the price we get after applying any Rules.

Check the screenshot below.



Hope this helps.

How to Show All Magento Orders Externally in PHP

The main objective is to show all the orders on a separate PHP page which won't be part of Magento.

So, we create a PHP script salesorders.php and put it in the root folder "public_html". We would use Magento's functionality by including its core files.

Now, let's check how we should start ...

<?php
error_reporting(1);

// Here We load Mage class
require_once 'app/Mage.php';

// BootStrap the Magento
Mage::app();

// GET ALL ORDERS
$orders = Mage::getResourceModel('sales/order_collection')
          ->addAttributeToSelect('*')
          ->addFieldToFilter('status', 
         array("in" => array('complete', 'closed'))
    )
          ->addAttributeToFilter('store_id', 
                  Mage::app()->getStore()->getId())
          ->addAttributeToSort('created_at', 'desc')
          ->load();
?>

In the above code, we are selecting all the Orders which have status either 'complete' or 'closed'. Also, we are fetching the Orders with the 'created_at' field in descending order.

Then we just need to iterate through the collection and generate an HTML. 

<?php 
foreach($orders as $order)
{
  /// GRAND TOTAL
  $grand_total = $order -> grand_total;

  /// CUSTOMER DETAILS
  $customer_email = $order -> customer_email;
  $customer_fname = $order -> customer_firstname;
  $customer_lname = $order -> customer_lastname;

  /// IF Customer names are blanks
  if($customer_fname == '' )
  {
   $billing_address_data = $order->getBillingAddress()->getData();
   $customer_fname = $billing_address_data['firstname'];
  }
  if($customer_lname == '' )
  {
    $billing_address_data = $order->getBillingAddress()->getData();
    $customer_lname = $billing_address_data['lastname'];
  }

  /// ORDER ID
  $increment_id = $order -> increment_id;
  $created_at   = $order -> created_at;

  $str  = "<tr>";
  $str .= "<td>$customer_fname $customer_lname <i>                              ($customer_email)</i></td>";
  $str .= "<td><b>$increment_id</b> Created on                              $created_at</td>";
  $str .= "<td>";

  /// GET all Visible Products
  /// purchased in the ORDER
  $items = $order->getAllVisibleItems();
  $largeItems = 0;

  /// LOOP thru ITEMs
  foreach($items as $i)
  {
    /// PRODUCT DETAILS
    $prod_id = $i->getProductId();
    $p = Mage::getModel('catalog/product')->load($prod_id);
    $sku = $p->getSku();
  
    /// Build HTML
    $str .=  "<a href='" . $p->getUrlPath() . "'>" . $i->getName() . "</a>";
  
    /// PRODUCT Options
    $prodOptions = $i->getProductOptions();
    /// LOOP thru product Options and Show Them
    foreach ( $prodOptions['attributes_info'] as $key => $val)
    {
$str .= "[" . $val['label'] . ":"; 
       $str .= $val['value'] . "] ";
    } 
  }

  $str .= "</td>";
  $str .= "</tr>";

  /// PRINT HTML
  echo $str ;
}
?>

Now check the Output we get.




Now, we can add a Search facility to our script; it will search the POSTed word with Customer name or email within the order. So, we need a <form> tag in our HTML. 

<form method="get" action="" id="search_mini_form">
    <input type="text" name="q" placeholder="Search Customer">
    <input  title="Search" type="submit" value="Search">
</form>

So, through PHP we need to receive this POSTed value and add some filtering code to the Order collection. The code is shown below. 

<?php
/// SEARCH 
if($_GET['q'] && trim($_GET['q']) != "")
{
  /// LIKE Query
  $likeStr = '%'.trim($_GET['q']).'%';

  $orders = Mage::getResourceModel('sales/order_collection')
      ->addAttributeToSelect('*')
      ->addFieldToFilter('status', array("in" => array(
           'complete', 'closed')
        ))
      ->addAttributeToFilter( 'store_id', 
               Mage::app()->getStore()->getId())
      ->addFieldToFilter( 
             array( 'customer_email', 'customer_firstname', 'customer_lastname'),
     array( array( 'like'=>$likeStr ), 
            array( 'like'=>$likeStr ), 
    array( 'like'=>$likeStr ) 
  )
)
      ->addAttributeToSort('created_at', 'desc')
      ->load();
    
  /// IF u want to show SQL
  /// uncomment below line
  /// echo $orders->getSelect()->__toString();
}
else
/// FOR Non-Search 
{
   $orders = Mage::getResourceModel('sales/order_collection')
       ->addAttributeToSelect('*')
       ->addFieldToFilter('status', array("in" => array(
            'complete', 'closed')
          ))
       ->addAttributeToFilter('store_id', 
            Mage::app()->getStore()->getId())
       ->addAttributeToSort('created_at', 'desc')
       ->load();

?>

If it is a search, then if($_GET['q'] && trim($_GET['q']) != "") is true and the first part of the if-else structure is executed. 

See, how we have captured the submitted value in variable "$likeStr" and used "addFieldToFilter" function for filtering the collection.

IF we need "AND" conditions, then we can use multiple addFieldToFilter() calls.

To use "OR", we need to modify the addFieldToFilter() as shown below.

->addFieldToFilter( 
array( 'customer_email', 
               'customer_firstname', 
               'customer_lastname'),
array( array( 'like'=>$likeStr ), 
      array( 'like'=>$likeStr ), 
       array( 'like'=>$likeStr ) 
     )
  )

above statement generates the following SQL

'customer_email' like $likeStr OR 'customer_firstname' like $likeStr OR 'customer_lastname' like $likeStr

To generate an "AND" SQL query like this :: 
'customer_email' like $likeStr AND 'customer_firstname' like $likeStr, 

we can use the following structure ::

->addFieldToFilter('customer_email',  array("like" => $likeStr))
->addFieldToFilter('customer_firstname',array('like'=>$likeStr))

You can download the full working code here.

In our next tutorial, we'll list all the products available in Magento from an external script.