Magento 1.9 – Order product collection by biggest percentage discount

The other day I had to create a new filter option for products which could order them by the largest discount. I made this simple workaround where I joined product collection with table “catalog_product_entity_decimal”, which is the table containing all the prices. “attribute_id” with value 76 is special_price.
Then, I created a new column “discount” which is calculated as:

discount = (price – special_price) / (price / 100)

 

// Join the special price into the discount column.
$store = Mage::app()->getStore();
    $_productCollection->getSelect()
                       ->joinLeft(
                           array( 'sfoi' => 'catalog_product_entity_decimal' ),
                           'e.entity_id = sfoi.entity_id AND sfoi.attribute_id = 76 AND sfoi.store_id = ' . $store->getId(),
                           array( 'discount' => '((price - sfoi.value) / (price / 100))' )
                       );
// Set order to DESC
    $_productCollection->getSelect()->Order( array( new Zend_Db_Expr( 'discount DESC' ) ) );

 


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How to create new products attribute programmatically

Attributes can be also created manually in Catalog > Attributes.
However, if your custom module requires to use new attributes, then the best practice is to create them programmatically, so when you install the module, new attributes will be created automatically without any further actions.

<?php  
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->startSetup();
$installer->addAttribute('catalog_product', 'magentoguides_attribute_key', array(
            'group'           => 'General',
            'label'           => 'Magento Guides front end label',
            'input'           => 'text',
            'type'            => 'varchar',
            'required'        => 0,
            'visible_on_front'=> 1,
            'filterable'      => 0,
            'searchable'      => 0,
            'comparable'      => 0,
            'user_defined'    => 1,
            'is_configurable' => 0,
            'global'          => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
            'note'            => '',
));
$installer->endSetup();

The new Attribute will be at the bottom of the product page by default. If you want to move it for example to prices tab. Then change ‘General’ to ‘Prices’. Or you can do it manually by navigating to Catalog > Manage attribute sets


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How to add block on every page in admin or front

Sometimes you might want to add block or javascript everywhere to the administration or everywhere to your theme. With Magento, this is very simple. What we need to do is to create a block and then extend layout separately for admin frontend. Also, we will need 2 separate templates.

Admin

Let’s start with Admin part first. We will create a custom module Magentoguides_JavascriptEverywhere.
Module config file with the path app\code\local\Magentoguides\JavascriptEverywhere\etc\config.xml
will have the following structure:

<?xml version="1.0"?>
<config>
    <modules>
        <Magentoguides_JavascriptEverywhere>
            <version>0.1.0</version>
        </Magentoguides_JavascriptEverywhere>
    </modules>
    <frontend>
        <layout>
            <updates>
                <javascripteverywhere>
                    <file>magentoguides_javascripteverywhere.xml</file> <!-- This is the layout file for Front -->
                </javascripteverywhere>
            </updates>
        </layout>
    </frontend>
    <adminhtml>
        <layout>
            <updates>
                <module>
                    <file>magentoguides_javascripteverywhere.xml</file> <!-- This is the layout file for Admin -->
                </module>
            </updates>
        </layout>
    </adminhtml>
    <global>
        <models>
            <magentoguides_javascripteverywhere>
                <class>Magentoguides_JavascriptEverywhere_Model</class>
                <resourceModel>magentoguides_javascripteverywhere_resource</resourceModel>
            </magentoguides_javascripteverywhere>
            <magentoguides_javascripteverywhere_resource>
                <class>Magentoguides_JavascriptEverywhere_Model_Resource</class>
            </magentoguides_javascripteverywhere_resource>
        </models>
        <blocks>
            <magentoguides_javascripteverywhere>
                <class>Magentoguides_JavascriptEverywhere_Block</class>
            </magentoguides_javascripteverywhere>
        </blocks>
        <helpers>
            <magentoguides_javascripteverywhere>
                <class>Magentoguides_JavascriptEverywhere_Helper</class>
            </magentoguides_javascripteverywhere>
        </helpers>
    </global>
</config>

Next step is to define a block at  app\code\local\Magentoguides\JavascriptEverywhere\Block\Adminhtml\EverywhereBlock.php

<?php

class Magentoguides_JavascriptEverywhere_Block_Adminhtml_EverywhereBlock extends Mage_Core_Block_Template
{

}

 

Then we will create the layout file which we defined in the config.xml app\design\adminhtml\default\default\layout\magentoguides_javascripteverywhere.xml

<?xml version="1.0"?>
<layout version="0.1.0">
    <default>
        <reference name="content">
            <block type="magentoguides_javascripteverywhere/adminhtml_everywhereBlock" name="securitycheck" template="magentoguides_javascripteverywhere/jseverywhere.phtml"/>
        </reference>
    </default>
</layout>

And lastly the template file app\design\adminhtml\default\default\template\magentoguides_javascripteverywhere\jseverywhere.phtml

<b>This html code will be shown everywhere!</b>
<script>
    alert('This javascript will be executed everywhere!');
</script>

 

Front

For the Front, we have to create same layout update file and same template file, however, in different directory since files for front and admin are separated.

Layout update file app\design\frontend\base\default\layout\magentoguides_javascripteverywhere.xml

<?xml version="1.0"?>
<layout version="0.1.0">
    <default>
        <reference name="content">
            <block type="magentoguides_javascripteverywhere/adminhtml_everywhereBlock" name="securitycheck" template="magentoguides/javascripteverywhere/myfile.phtml"/>
        </reference>
    </default>
</layout>

Template file with same content as the one we created above app\design\frontend\base\default\template\magentoguides\javascripteverywhere\myfile.phtml

<b>This html code will be shown everywhere!</b>
<script>
    alert('This javascript will be executed everywhere!');
</script>

 

Download module


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Export Products in Magento 1 From Terminal Via SSH

Prerequisites

You will need SSH access to your Magento website.

 

First you will need to find id of your data profile. Go to your Magento backend and:

System > Import/Export > Dataflow – Profiles

By default, for exporting products it should be id 1.

Create a file custom_product_export.php in the root of your magento app with following code:

 

<?php


set_time_limit(0);
// THIS SCRIPT JUST INITIALS THE PROFILE TO BE RUN VIA MAGENTO ADMIN "RUN PROFILE IN POPUP". Its the same thing as click just via this file that you can run via cron
$profileId = 1; // ID of your data profile

require_once 'app/Mage.php';
umask(0);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

$profile = Mage::getModel('dataflow/profile');
$userModel = Mage::getModel('admin/user');
$userModel->setUserId(0);
Mage::getSingleton('admin/session')->setUser($userModel);
$profile->load($profileId);
if (!$profile->getId()) {
    Mage::getSingleton('adminhtml/session')->addError('ERROR: Incorrect profile id');
}

Mage::register('current_convert_profile', $profile);
$profile->run();
$recordCount = 0;
$batchModel = Mage::getSingleton('dataflow/batch');
echo "EXPORT COMPLETE. BATCHID: " . $batchModel->getId();

now run the script with

php custom_product_export.php

 

If you will get error Allowed memory size exhausted, try run it like this

php -dmemory_limit=50G custom_product_export.php

Your Exported .csv file will be saved in magento root var/export/ folder.


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Add System Configuration Fields

We are going to add new configuration input.

Creating new system configuration inputs is very convenient in magento, since there is no need to do anything with database.

Create system.xml in your module etc/ directory.

<config>
    <sections>
        <general translate="label">
            <groups>
                <example>
                    <label>Example options</label>
                    <sort_order>0</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <some_field translate="label">
                            <label>Some Field</label>
                            <frontend_type>text</frontend_type>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </some_field>
                    </fields>
                </example>
            </groups>
        </general>
    </sections>
</config>

Usage

You can get the value of your configuration field by calling this function in code.

Mage:getStoreConfig('general/example/some_field');
//general - this is section
//example - this is group
// some_field - this is field
/*Follow the system.xml to know where they come from*/

 


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
Create New Admin User From SQL
SET @SALT = "rp";
SET @PASS = CONCAT(MD5(CONCAT( @SALT , "password") ), CONCAT(":", @SALT ));
SELECT @EXTRA := MAX(extra) FROM admin_user WHERE extra IS NOT NULL;
 
INSERT INTO `admin_user` (firstname,lastname,email,username,password,created,lognum,reload_acl_flag,is_active,extra,rp_token_created_at) 
VALUES ('Firstname','Lastname','email@example.com','myuser',@PASS,NOW(),0,0,1,@EXTRA,NOW());
 
INSERT INTO `admin_role` (parent_id,tree_level,sort_order,role_type,user_id,role_name) 
VALUES (1,2,0,'U',(SELECT user_id FROM admin_user WHERE username = 'myuser'),'Firstname');

Credit: activo


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Create Database Table Via Module

Module setup script

[ModuleRoot]/sql/[namespace]_[moduleName]_setup/install-0.1.0.php

$installer = $this;
$installer->startSetup();

$connection = $installer->getConnection();
$connection->beginTransaction();

try {

  $table  = $connection->newTable($installer->getTable('database_books/books'))
                       ->addColumn('database_actor_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
                         'unsigned'  => true,
                         'nullable'  => false,
                         'primary'   => true,
                         'identity' => true,
                       ), 'ID actor')
                       ->addColumn('title', Varien_Db_Ddl_Table::TYPE_VARCHAR, null, array(
                         'unsigned'  => true,
                         'nullable'  => false,
                         'primary'   => false,
                       ), 'Firstname')
                       ->addColumn('isbn', Varien_Db_Ddl_Table::TYPE_VARCHAR, null, array(
                         'unsigned'  => true,
                         'nullable'  => false,
                         'primary'   => false,
                       ), 'Lastname');

  $connection->createTable($table);

  $connection->commit(); // Execute SQL,

}catch(Exception $e) {
  Mage::log($e->getMessage());
  $connection->rollBack(); // In case of some error, php revert changes
}

 

Module’s config.php

Our new table has to be declared.

<global>
   <models>
            <pfay_films>
                <class>Pfay_Films_Model</class>
                <resourceModel>pfay_films_resource</resourceModel>
            </pfay_films>
            <pfay_films_resource>
                <class>Pfay_Films_Model_Resource</class>
                <entities>
                    <actors>
                        <table>pfay_actors</table>
                    </actors>
                </entities>
            </pfay_films_resource>
        </models>
</global>

Model

To run our script we need to create model as well.

Once we’re done, we can access data like this

$installer->getTable('pfay_films/actors')

 


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Create Page in Admin Panel

Our Namespace is Guides and module name is Films.

Modules config.xml

<config>
    <modules>
        <Guides_Films>
            <version>0.1.0</version>
        </Guides_Films>
    </modules>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <films before="Mage_Adminhtml">Guides_Films_Adminhtml</films>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
    <adminhtml>
        <layout>
            <updates>
                <films>
                    <file>guides_films.xml</file>
                </films>
            </updates>
        </layout>
    </adminhtml>
    <global>
        <blocks>
            <guides_films>
                <class>Guides_Films_Block</class>
            </guides_films>
        </blocks>
        <helpers>
            <guides_films>
                <class>Guides_Films_Helper</class>
            </guides_films>
        </helpers>
    </global>
</config>

Modules adminhtml.xml

<config>
    <menu>
        <guides translate="title" module="guides_films">
            <title>Guides Menu</title>
            <sort_order>100</sort_order>
            <children>
                <films translate="title" module="guides_films">
                    <title>Films</title>
                    <sort_order>0</sort_order>
                    <action>adminhtml/film/index</action>
                </films>
            </children>
        </guides>
    </menu>
</config>

Helper Data.php

<?php

class Guides_Films_Helper_Data extends Mage_Core_Helper_Abstract {

}

Block Movieblock.php

<?php
class Guides_Films_Block_Movieblock extends Mage_Core_Block_Template
{
    public function methodblock() {
        return 'test from method block';
    }
}

Controllers/Adminhtml/FilmController.php

<?php

class Guides_Films_Adminhtml_FilmController extends Mage_Adminhtml_Controller_Action {

  public function indexAction() {
    $this->loadLayout();
    $this->renderLayout();

  }

}

app/design/adminhtml/default/default/layout/guides_films.xml

<layout version="1.0">

    <adminhtml_film_index>

        <reference name="content">
            <block type="guides_films/movieblock" name="monblock" template="guides_films/movies.phtml" />
        </reference>
    </adminhtml_film_index>

</layout>

app/design/adminhtml/default/default/template/guides_films/movies.phtml

<h1>Hello World</h1>
<p>This is test from movies.phtml</p>
<?php echo $this->methodblock(); ?>

 


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Create Helper

Prerequisities

You need to have a custom module for this. Assuming we have a module with namespace Guides and module name Meta.

Creating a Helper

Helpers are used to help you obviously. Usually you will use them for general functions which you can use everywhere and those functions are not suitable for placing them into a model.

<config>
    <modules>
        <guides_meta>
            <version>1.0.0</version>
        </guides_meta>
    </modules>
    <global>
        <helpers>
            <guides_meta>
                <class>Guides_Meta_Helper</class>
            </guides_meta>
        </helpers>
    </global>
</config>
<?php

class Guides_Meta_Helper_Data extends Mage_Core_Helper_Abstract {

  public function get_content() {
    return 'This is the content from Helper';
  }
}

Now you have to somewhere call our new Helper method. You can do it like this and reuse it anytime you want.

$helper = Mage::helper('guides_meta'); // Assuming that our helper is Data.php, if it had a different name than you have you append _Filename in the end

echo $helper->get_content(); // Calls our defined method

/* output will be: This is the content from Helper */

 

 

 


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.
How To Create Observers // Customer logout

Prerequisities

Again we need our own mudule. Assuming we have module with namespace Guides and module name Meta

Static and dynamic events

We can divide Magento events into static and dynamic.

Static are:

Mage::dispatchEvent('admin_session_user_login_failed', array('user_name' => $username, 'exception' => $e));

Mage::dispatchEvent('cms_page_prepare_save', array('page' => $model, 'request' => $this->getRequest()));

Mage::dispatchEvent('catalog_product_get_final_price', array('product' => $product, 'qty' => $qty));

Mage::dispatchEvent('catalog_product_flat_prepare_columns', array('columns' => $columnsObject));

Mage::dispatchEvent('catalog_prepare_price_select', $eventArgs);

Dynamic are:

Mage::dispatchEvent($this->_eventPrefix.'_load_before', $params);

Mage::dispatchEvent($this->_eventPrefix.'_load_after', $this->_getEventData());

Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());

Mage::dispatchEvent($this->_eventPrefix.'_save_after', $this->_getEventData());

Mage::dispatchEvent('controller_action_layout_render_before_'.$this->getFullActionName());

Let’s say we want to execute our code before we edit new page in Magento admin panel. When you check core files and the save method, you will see this code

Mage::dispatchEvent('cms_page_prepare_save', array('page' => $model, 'request' => $this->getRequest()));

What interest us is the name of the event: cms_page_prepare_save.

Create observer

Create file app/code/local/Guides/Meta/Model/Observer.php

we will put this code inside

<?php
echo "Im here";
class Guides_Meta_Model_Observer extends Varien_Event_Observer {
  public function __construct() {

  }

  public function saveCmsPageObserve( $observer ) { // We chose this method name.
    $event = $observer->getEvent();
    $model = $event->getPage();
    print_r( $model->getData() );
    die( 'test' );
  }
}

Register Model and Observer in module config

<config>
    <modules>
        <guides_meta> <!-- **Note the lowercase -->
            <version>1.0.0</version>
        </guides_meta>
    </modules>
    <global>
        <models>
            <guides_meta> <!-- **Note the lowercase -->
                <class>Guides_Meta_Model</class> <!-- We have to register our model first. -->
            </guides_meta>
        </models>
        <events>
            <cms_page_prepare_save> <!-- This is the event name -->
                <observers>
                    <guides_meta>
                        <type>Singleton</type>
                        <class>guides_meta/observer</class> <!-- Than we assign our class with method which will be executed when event happens **Note the lowecase letters.. -->
                        <method>saveCmsPageObserve</method> 
                    </guides_meta> <!-- **Note the lowercase -->
                </observers>
            </cms_page_prepare_save>
        </events>
    </global>
</config>

Now go to your admin panel.

where-to-edit-page

Click on some page, edit it a click save.

Than you should see something like this.

edit page how it looks like


Lukas
Lukas Stranovsky
I am the guy who made this. Sorry for typos.