Viewed   56 times

I am using Magento to build an eBooks site. For the release, we plan to have a number of free downloadable books. We were hoping that it would be possible to use the normal Magento 'catalog' functionality to add categories with products underneath. However, since these are free downloadable products, it doesn't really make sense to send users through the checkout when they try to download.

Does anyone know of a way to create a free downloadable product which bypasses the checkout altogether? I have noticed that there is a 'free sample' option for downloadable products, but I would prefer not to use this if I can as I plan to use this field for its intended purpose when I add paid products.

[EDIT] I have noticed that some of you have voted this question down for 'lack of question clarity'. For clarity, I want:

  1. to know if it is possible to create a downloadable product in Magento which doesn't require users to go through the usual checkout process (since it is free)
  2. and which is not the 'Free Sample' field of a downloadable product

Unfortunately I don't think I can ask this any more eloquently. [/EDIT]



This code will allow logged-in customers to "place an order" for a Free, Virtual product while bypassing checkout and redirect them straight to the My Downloads section of their account.

Add the following line to your catalog/product/list.phtml in the spot you want it.

<?php if($_product->isVirtual() && $_product->getFinalPrice()==0) { ?>
                <a href="/modulename/checkout/purchase/id/<?php echo $_product->getId()?>"><?php echo $this->__('Download and Install') ?></a>
            <?php } ?>

Then create a new module with a controllers/CheckoutController.php containing this code:

public function purchaseAction() {
if (!Mage::getSingleton('customer/session')->isLoggedIn()) {
 $request = $this->getRequest();
 $id = $request->getParam('id');
 $product = Mage::getModel('catalog/product')
 if(!($product->getIsVirtual() && $product->getFinalPrice() == 0)){
     Mage::getSingleton('checkout/session')->addError($this->__('Method only available for Free Downloadable Items'));
     return $this;
 $onepage = Mage::getSingleton('checkout/type_onepage');
 /* @var $onepage Mage_Checkout_Model_Type_Onepage */
     $quote = $onepage->getQuote();
     /* @var $quote Mage_Sales_Model_Quote */
 catch(Exception $e){
     $result = $e->getMessage();

You'll need to handle the Exceptions a little better, but that should be functionally correct.

Sunday, September 11, 2022

Fished my own wish after hacking on it for a while

$now = Mage::getSingleton('core/date')->timestamp( time() );
$websiteId = Mage::app()->getStore()->getWebsiteId();
$customerGroup = 4;

Mage::getResourceModel('catalogrule/rule')->getRulePrice( $now, $websiteId, $customerGroup, $_productId);
Saturday, December 17, 2022

Perhaps instead of:

$ingredientsArray = array($ingredientsArrayContent);

try using:

$ingredientsArray = array(explode(",",$ingredientsArrayContent));

Depending on whether your attribute is set as: "water,salt,colourings" or "water, salt, colourings" your delimiter might need to change or how you set your attribute values might need to change.

Thursday, September 29, 2022

Nov 2020 Update

To make it work with a product category you can use the WordPress conditional function has_term() this way:

add_action('woocommerce_single_product_summary', 'remove_product_description_add_cart_button', 1 );
function remove_product_description_add_cart_button() { // function for deleting ...
    // Set HERE your category ID, slug or name (or an array)
    $categories = array('your-category-1');

    //Remove Add to Cart button from product description of product with id 1234
    if ( has_term( $categories, 'product_cat', get_the_id() ) ) {
        remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );

Code goes in function.php file of your active child theme (or active theme). Or also in any plugin php file. Tested and works.

Monday, November 7, 2022

tl;dr: The answer to this question varies in complexity based on product type (configurable, simple, etc.). This may drive how you setup your catalog and set simple product visibility. If all that you have in your catalog is simple items, this task is very easy. Also: see edit at end.

There are lots of scenarios to consider. For example, if you add a configurable item to the cart, the quote will have two quote items per option: one quote item for the configurable parent product which will contain option quantity information and one quote item which will provide the option's simple product data. Bundle items will have a parent bundle item as well as a simple item for each bundle option.

What this boils down to is that you need to decide how you represent each product type's quantity to the user; for example, do you want to represent the same model of shirt as one line item with all size quantities, or do you want to separate these out for each size (the latter being how Magento renders them in cart / review areas).

I recommend adding your products to the cart, then using this in the frontend to see the quote item data:


include 'app/Mage.php';

Mage::app(); // Mage_Core_Model_App

Mage::getSingleton('core/session', array('name'=>'frontend'));

$quote = Mage::helper('checkout/cart')->getCart()->getQuote();

echo count($quote->getItemsCollection());
foreach ($quote->getItemsCollection() as $item){

I recommend using an install with the sample data and adding different quantities of each product type to the cart. Based on this + the output from the above code, you'll see that you have several approaches and gotchas as you loop through. The confounding scenarios are when you have the following:

  • Configurable items
    • For each option, you'll have the configurable product as an item and the simple product from which the option is derived as an item. If you want to display the total count by the configurable parent, you'll need to tally the total configurable qty in the loop:


$configurables = array();

// ...then, inside your foreach
if($item->getProductType() === 'configurable'){
        //add to the other options' quantity
        $configurables[$item->getProductId()] += $item->getQty();
    else {
        $configurables[$item->getProductId()] = $item->getQty();
  • Grouped Items
    • Simple products which are added to the quote as part of a grouped item are separate from simple items which are added individually and other groups to which they may belong. If you want to aggregate these, you can loop through like so:


$grouped = array();

// ...then, inside your foreach
if($item->getProductType() === 'grouped' || $item->getProductType() === 'simple'){
        //add to the other options' quantity
        $grouped[$item->getProductId()] += $item->getQty();
    else {
        $grouped[$item->getProductId()] = $item->getQty();
  • Bundle Items
    • Bundle product quote items are represented by one item for the bundle product and separate simple product items for each option. The simple product items have the quantity information stored against them. The simple items have a parent item ID which referes back to the bundle product quote item, just as configurable product quote items' children items do.

You can see that handling all scenarios is cumbersome. I wish I could tell you that it's easier to do this via resource models, but the fact is that in the database the sales_flat_quote_item_option table stores quantity info in a column of serialized data, so you'll need to pull things into PHP to get anywhere with them (which is done for you via the resource model).

Sorry this is such a long answer, but you can see that, based on your catalog setup, you're in for some careful consideration and testing to make sure you've got your bases covered.

EDIT: While trying to be thorough, I failed to mention that you should look into the sales_flat_quote_item table. Depending on your requirements, you can easily use the data in there to quickly, gracefully, and efficiently model the data that you need to achieve your display requirements.

Monday, November 28, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :