Archive for the ‘Magento’ Category

Simple Customer objects in Magento

Monday, May 7th, 2012

Have you ever just needed the customers company name or first name, or some custom customer attribute?

Well, I am tired of loading the entire customer object for just 2 or 3 things.

I have 2 custom customer attributes that I need, companyname and companywebsite

This would work for regular things like first name and last name as well!

Here is how:

Version 1:

// Get the customer data and set it on the object as companyname
 $customer = Mage::getModel('customer/customer')
 ->getCollection()
 ->addFieldToFilter('entity_id', array('eq' => $customer_id))
 ->addAttributeToSelect('companyname')
 ->addAttributeToSelect('companywebsite')
 ->getItems();
$company_name = $customer[$customer_id]->getData('companyname');
$company_website = $customer[$customer_id]->getData('companywebsite');

Version #2 is slightly more easy to use

// Get the customer data and set it on the object as companyname
 $customer = Mage::getModel('customer/customer')
 ->getCollection()
 ->addFieldToFilter('entity_id', array('eq' => $customer_id))
 ->addAttributeToSelect('companyname')
 ->addAttributeToSelect('companywebsite')
 ->getLastItem();
$company_name = $customer->getData('companyname');
$company_website = $customer->getData('companywebsite');

As you can see, version 1 needs to go through the array before you can have access to the method getData.

I would recommend version 2 as it stays with the typical way of doing things ( aka the magento way ).

 

Magento – how to decode the referer part of a URL

Friday, April 27th, 2012

If you have ever wondered how to figure out what that long string of letters and numbers are in a magento URL, here is how to do it.

Lets say that our URL is:

$string = 'www.whatever.com/customer/account/login/referer/aHR0cDovL2xvY2FsLmJsb29tMi5jb20vc2hvcA,,/';
Mage::helper('core')->urlDecode($string);

From what I can tell, it does the same thing as

base64_decode($string);

That will be decoded as

www.whatever.com/shop

Pretty fancy work there Magento! But I got you figured out.

Adding Custom Module with Custom Database Table

Friday, April 20th, 2012

http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/custom_module_with_custom_database_table

How to get a block in a controller

Monday, April 16th, 2012

If you are in a Magento Controller and you need to get a different block and its methods….here is how:

// This function would be in a controller called something like CustomerController.php

class Bloom_BeautyBio_CustomerController extends Mage_Core_Controller_Front_Action
{
public function viewAction()
    {

/******** This is the secret sauce that gives you access to the class and its methods   ******/
        $viewingOthers = $this->getLayout()->createBlock('beautybio/beautybio')->viewingOtherMember();

        if($viewingOthers)
        {
            $this->_redirect('beautybio/customer/view/#photos');
            exit();
        }

        $this->loadLayout(array('default'));
        $this->renderLayout();
    }
}

Magento: Get a rough total for all rows in all tables in mysql

Tuesday, February 14th, 2012

$query = “SELECT table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ‘database_name_goes_here’”;

$result = Mage::getSingleton(‘core/resource’) ->getConnection(‘core_read’)->fetchAll($query);
$total = 0;

for( $i = 0; $i {
$total += $result[$i]['table_rows'];

}
echo ‘Grand Total = ‘ . $total;

Redhat – Sort log file by date

Sunday, February 12th, 2012

$ ls -l -r –sort=time

magento and ajax

Wednesday, January 25th, 2012

http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-3-magento-controller-dispatch

Good tutorial

Magento – get shipping amount for a quote

Sunday, January 22nd, 2012

If your on the checkout/cart page, you can get the shipping totals:
$shipping_total = $this->getQuote()->getShippingAddress()->getShippingAmount();

Magento addAttributeToFilter

Wednesday, January 4th, 2012
  • Using Collections in Magento

A collection is a Model type containing other Models, it is basically used in Magento to handle product lists (ie. from a category or a bundle option), but not only.

TO DO: Explain how Magento Implements a collection – Use this to explain how Magento implements a collection by looking at code in a model, so that people can learn to write their own collections

This is a simple example of loading some product collection from a category and ordering them on their product name using Magento’s API.

$collection = Mage::getModel(‘catalog/category’)->load($categoryId)->getProductCollection()->addAttributeToSort(‘name’, ‘ASC’);

To sort using multiple Fields, you can chain calls to the Collection’s method addAttributeToSort(preferred)

$collection = Mage::getModel(‘module/model_name’)->getCollection()->addAttributeToSort(‘order’, ‘ASC’)->addAttributeToSort(‘last_name’, ‘ASC’)->addAttributeToSort(‘first_name’, ‘ASC’);

TODO: use Magento’s API use cases, not Zend_Db_Select ones.

You can also pass IF/THEN statements, but be sure to use the proper quotation of your table’s fields.

  1. $collection = Mage::getModel(‘module/model_name’)->getCollection();
  2. $collection->getSelect()->order( array(‘IF(`order`>0, `order`, 9999) ASC’,'last_name ASC’, ‘first_name ASC’) );

In this example, the table will be sorted by the order field, then by last name, then by first name, where order is greater than zero, followed by order being equal to or less than zero, all ascending.

Joining Tables

To add SQL joins to a select

  1. $collection = Mage::getModel(‘module/model_name’)->getCollection();
  2. $collection->getSelect()->join( array(‘table_alias’=>$this->getTable(‘module/table_name’)), ‘main_table.foreign_id = table_alias.primary_key’, array(‘table_alias.*’), ‘schema_name_if_different’);

In this example the join method takes an array of alias⇒table_name key pairs, then a standard join clause using `main_table` to refer to the original select, then an array of fields to be retrieved in the join (defaults to *), a different schema can be specified as a last parameter.

→join defaults to an inner join, others can be used:

→joinInner() →joinLeft() →joinRight() →joinFull() →joinCross() →joinNatural()

See lib/Zend/Db/Select.php for source.

Collection Manipulation Methods

Varien_Data_Collection

Varien/Data/Collection.php

addFilter($field, $value, $type = ‘and’)
addItem(Varien_Object $item)
clear()
count()
distinct($flag)
each($obj_method, $args=array())
getAllIds()
getCacheKey()
getCacheLifetime()
getCacheTags()
getColumnValues($colName)
getCurPage($displacement = 0)
getFirstItem()
getFlag($flag)
getItemByColumnValue($column, $value)
getItemById($idValue)
getItems()
getItemsByColumnValue($column, $value)
getIterator()
getLastItem()
getLastPageNumber()
getNewEmptyItem()
getPageSize()
getSize()
hasFlag($flag)
isLoaded()
loadData($printQuery = false, $logQuery = false)
load($printQuery = false, $logQuery = false)
removeItemByKey($key)
setCacheKey($key)
setCacheTags($tags)
setCurPage($page)
setDataToAll($key, $value=null)
setFlag($flag, $value = null)
setOrder($field, $direction = self::SORT_ORDER_DESC)
setPageSize($size)
toArray($arrRequiredFields = array())
toOptionArray()
toOptionHash()
toXml()
walk($callback, array $args=array())

Varien_Data_Collection_Db

Varien/Data/Collection/Db.php

Inherits above methods for Varien_Data_Collection, and in addition (re)defines the following:

addBindParam($name, $value)
addFieldToFilter($field, $condition=null)
addOrder($field, $direction = self::SORT_ORDER_DESC)
distinct($flag)
getConnection()
getData()
getIdFieldName()
getSelect()
getSelectCountSql()
getSize()
initCache($object, $idPrefix, $tags)
loadData($printQuery = false, $logQuery = false)
load($printQuery = false, $logQuery = false)
printLogQuery($printQuery = false, $logQuery = false, $sql = null)
resetData()
setConnection($conn)
setOrder($field, $direction = self::SORT_ORDER_DESC)
unshiftOrder($field, $direction = self::SORT_ORDER_DESC)

Filter Condition Codes

Attribute Code SQL Equivalent Description
eq =
neq !=
like LIKE
nlike NOT LIKE
in IN ()
nin NOT IN ()
is IS
notnull IS NOT NULL
null IS NULL
moreq >=
gt >
lt <
gteq >=
lteq <=
finset FIND_IN_SET()
from >= for use with dates
to <= for use with dates
date optional flag for use with from/to to specify that comparison value should first be converted to a date
datetime optional flag for use with from/to to specify that comparison value should first be converted to a datetime

If an array is passed but no attribute code specified, it will be interpreted as a group of OR conditions that will be processed in the same way.

If no attribute code is specified, it defaults to eq.

E.g.

  1. $collection->addAttributeToFilter(‘field_name’, array(
  2.     ‘in’ => array(1, 2, 3),
  3.     ));
  4. $collection->addAttributeToFilter(‘date_field’, array(
  5.    ’from’ => ’2000-09-10′,
  6.     ));
  7. $collection->addAttributeToFilter(‘date_field’, array(
  8.     ‘from’ => ’10 September 2000′,
  9.     ‘from’ => ’11 September 2000′,
  10.     ‘date’ => true, // specifies conversion of comparison values
  11.     ));
  12. $collection->addAttributeToFilter(‘field_name’, 1); // tests for equality
  13. // Add OR condition:
  14. $collection->addAttributeToFilter(array(
  15.     array(
  16.         ‘attribute’ => ‘field_name’,
  17.         ‘in’        => array(1, 2, 3),
  18.         ),
  19.     array(
  20.         ‘attribute’ => ‘date_field’,
  21.         ‘from’      => ’2000-09-10′,
  22.         ),
  23.     ));

Mage_Eav_Model_Entity_Collection

Mage/Eav/Model/Entity/Collection/Abstract.php

Inherits above methods for Varien_Data_Collection_Db, and in addition (re)defines the following:

addAttributeToFilter($attribute, $condition=null, $joinType=’inner’) adds WHERE clause on $attribute specified by $condition
addAttributeToSelect($attribute, $joinType=false) gets the value for $attribute in the SELECT clause;
specify * to get all attributes (i.e. to execute SELECT *)
addAttributeToSort($attribute, $dir=’asc’) adds ORDER BY clause on $attribute
addEntityTypeToSelect($entityType, $prefix) doesn’t seem to do anything – don’t use
addExpressionAttributeToSelect($alias, $expression, string|array $attribute) adds SQL expression $expression, using $alias, to SELECT clause (typically containing aggregate functions such as SUM(), COUNT());
when $attribute specifies a single attribute as a string, $expression can reference the attribute as simply {{attribute}}, but when passing an array of attributes, each attribute must be referenced in $expression by the name of the specific attribute;
N.B. use with groupByAttribute() when including aggregate functions q.v.
addFieldToFilter($attribute, $condition=null) alias for addAttributeToFilter()
addItem(Varien_Object $object) adds an object to the collection
addStaticField($field) specifies $field as being static, i.e. as existing on the entity table itself, rather than in the EAV table
delete() deletes all entities in the collection
exportToArray() returns collection data as a 2D array
getAllIds($limit=null, $offset=null) returns array of all entity IDs selected by current WHERE clause (optionally specifying $limit and $offset)
getAllIdsSql() not recommended – don’t use
getAttribute($attributeCode) for specified $attributeCode, returns Mage_Eav_Model_Entity_Attribute_Abstract object of the entity object used by the collection (i.e. calls getAttribute($attributeCode) on the entity object and returns the result)
getEntity() returns Mage_Eav_Model_Entity_Abstract object used by collection for attributes
getLoadedIds() returns array of IDs of currently loaded entities
getResource() returns Mage_Core_Model_Resource_Abstract instance;
actually an alias for getEntity() q.v. (an entity is a special type of resource, that is, Mage_Eav_Model_Entity_Abstract extends Mage_Core_Model_Resource_Abstract)
getRowIdFieldName() returns field name of ID attribute for entities in the collection
getTable($table) alias for Mage::getSingleton(‘core/resource’)->getTableName($table)
groupByAttribute($attribute) adds $attribute to GROUP BY clause
importFromArray($arr) imports 2D array into collection as objects
joinAttribute($alias, Mage_Eav_Model_Entity_Attribute_Abstract|string $attribute, string $bind, string $filter=null, string $joinType=’inner’, $storeId=null) joins another entity and adds attribute from joined entity, using $alias, to SELECT clause;
$attribute can specify attribute object, or string in format [entity]/[attribute];
$bind specifies attribute of the main entity on which to make join;
$filter specifies primary key of the joined entity on which to make join (normally defaults to entity_id);
$joinType should be inner or left
joinField($alias, $table, $field, $bind, $cond=null, $joinType=’inner’) joins regular table field using an attribute as foreign key
joinTable($table, $bind, $fields=null, $cond=null, $joinType=’inner’) joins table $table
load($printQuery = false, $logQuery = false) runs query and load data into collection;
specify $printQuery as true to print SQL for debugging
removeAttributeToSelect($attribute=null) removes $attribute from SELECT clause;
specify null to remove all attributes
save() saves all entities in the collection
setEntity(string|object $entity) sets entity object (i.e. Mage_Eav_Model_Entity_Abstract) used by collection for attributes
setObject(Varien_Object $object=null) sets template object for the collection
setOrder(string| $attribute, $dir=’desc’) alias for addAttributeToSort() q.v., identical except that it can accept array of attributes, and default $dir is desc;
N.B. overrides parent function
setPage($pageNum, $pageSize) sets LIMIT clause by specifying page number (one-indexed) and number of records per page;
N.B. equivalent to calling setCurPage($pageNum) and setPageSize($pageSize) q.q.v.
setRowIdFieldName($fieldName) returns field name of ID attribute for entities in the collection
toArray(array $arrAttributes=array()) calls toArray($attAttributes) on each entity in collection, and returns result as array

Magento enterprise – Send out reminder emails to invited guests

Wednesday, December 21st, 2011

We needed to send a friendly reminder to some guests who have been invited to our Magento Enterprise store but never accepted.   We have a plugin that creates coupon codes and had it dump to a CSV and gave them some free reward points to spend if they came to our site and joined.

1. create the xml for our new Module in our package Bloom:

In app/etc/modules/ create a file called Bloom_SecondChanceEmail.xml

<?xml version="1.0"?>
<config>
<modules>
   <Bloom_SecondChanceEmail>
      <active>true</active>
      <codePool>local</codePool>
      <version>0.0.1</version>
   </Bloom_SecondChanceEmail>
</modules>
</config>

2. Create a folder and sub folders in /app/code/local/Bloom/

New folder SecondChanceEmail

New sub folders: etc, Model and sql

Inside etc create a file called config.xml

<?xml version="1.0"?>
<config>
	<modules>
		<Bloom_SecondChanceEmail>
			<version>0.0.1</version>
		</Bloom_SecondChanceEmail>
	</modules>
	<global>
        <models>
            <bloom_secondchanceemail>
                <class>Bloom_SecondChanceEmail_Model</class>
           	</bloom_secondchanceemail>
        </models>
		<resources>
            <secondchanceemail_setup>
                <setup>
                    <module>Bloom_SecondChanceEmail</module>
                </setup>
            </secondchanceemail_setup>
        </resources>
    	<template>
	      <email>
	        <secondchance_email_template translate="label" module="secondchanceemail">
	          <label>Second Chance Email</label>
	          <file>secondchance.html</file>
	          <type>html</type>
	          </secondchance_email_template>
	        </email>
	      </template>
	</global>
</config>

Inside Model create a file called Observer.php

<?php

class Bloom_SecondChanceEmail_Model_Observer {

    public function sendSecondChanceEmails() {

            $baseUrl    = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);

            // get the template for sending the reminder email
            $templateId = Mage::getStoreConfig('secondchance_email/template');

            // subject
            $mailSubject = 'Your friend has sent you a gift from Bloom.com';

            // Sender email
            $sender = array(
                'name' => Mage::getStoreConfig('trans_email/ident_support/name'),
                'email' => Mage::getStoreConfig('trans_email/ident_custom1/email')
            );

            $supportEmail = Mage::getStoreConfig('trans_email/ident_support/email');

            $supportPhone = Mage::getStoreConfig('general/store_information/phone');

            $days_back = 45;

            $dateStart = date( "Y-m-d H:i:s", mktime( 0,0,0, date( "m" ), date( "d" ) - $days_back, date( "Y" ) ) );
            $dateEnd   = date( "Y-m-d H:i:s", mktime( 23,59,59, date( "m" ), date( "d" ), date( "Y" ) ) );

                //$pendingInvite = Mage::getModel('enterprise_invitation/invitation')->getCollection()->addFieldToFilter('status','sent');
            $pendingInvitations = Mage::getModel('enterprise_invitation/invitation')->getCollection()
             ->addFieldToFilter('date', array('from' => $dateStart, 'to' => $dateEnd))
             ->addFieldToFilter('status','sent')->getData();

        $row = 0;
        $file = $baseUrl . "secondchance.csv";
        $coupon_array = array();
        if (($handle = fopen($file, "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
                     $coupon_array[$row] = $data[0];
                $row++;
            }
            fclose($handle);
        }
            foreach( $pendingInvitations as $invite )
            {
                $storeId = $invite['store_id'];
                // Load the skin url based on the store ID
                Mage::app()->setCurrentStore($storeId);

                $customer_data = Mage::getModel('customer/customer')
                                    ->setWebsiteId(Mage::app()->getStore()->getWebsiteId())
                                    ->loadByEmail($invite['email'])->getData();

                if($customer_data)
                {
                    // Do nothing for now
                }
                else
                {
                    $couponCode = $coupon_array[$i];
                    // Set variables that can be used in email template
                    $vars = array(
                        'customerName' => $customerName,
                        'customerEmail' => $invite['email'],
                        'supportPhone' => $supportPhone,
                        'supportEmail' => $supportEmail,
                        'couponCode' => $couponCode
                    );

                        $translate = Mage::getSingleton('core/translate');

                        Mage::getModel('core/email_template')
                                ->setTemplateSubject($mailSubject)
                                ->sendTransactional($templateId, $sender, $invite['email'], $customerName, $vars, $storeId);
                        $translate->setTranslateInline(true);

                }
            }
    }
}

In sql create a folder called  secondchanceemail_setup

Inside the new folder secondchanceemail_setup create a file called mysql4-install-0.0.1.php

<?php

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

/* @var $installer Mage_Core_Model_Resource_Setup */

$configValuesMap = array(
  'secondchance_email/template' =>
  'secondchance_email_template',
);

foreach ($configValuesMap as $configPath=>$configValue) {
	$installer->setConfigData($configPath, $configValue);
}

$installer->endSetup();

In the main folder of your site create a csv file called secondchance.csv and put in some coupon codes but make sure you have either exactly how many you need to fulfill every invite or better yet a few more (we needed 4000! ). Here is a sample:

19VCH27
17LUG62
17FUE65
16UVL45
15PFC32
14ECJ28
13GJU35
14ENS67
15DHV65
15FUT82
14EAV75
13RAK87
14UNL82
13EUN73
15ETC64
11RWX25
12LPM45
12WVP73
13WCN32
12GNF86
12VUT98
13ARC82
13XNV78

Last step is to create a file in shell/ called secondChanceEmail.php

<?php
/**
 * Magento Enterprise Edition
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Magento Enterprise Edition License
 * that is bundled with this package in the file LICENSE_EE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.magentocommerce.com/license/enterprise-edition
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @category    Mage
 * @package     Mage_Shell
 * @copyright   Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
 * @license     http://www.magentocommerce.com/license/enterprise-edition
 */

require_once 'abstract.php';

/**
 * Magento Log Shell Script
 *
 * @category    Mage
 * @package     Mage_Shell
 * @author      Magento Core Team <core@magentocommerce.com>
 */
class Mage_Shell_secondAttemptSendInvite extends Mage_Shell_Abstract
{
    /**
     * Run script
     *
     */

    public function run()
    {
        /*
         * MAKE NOTE!!!!!!!
         *
         * this transaction is not saved, so if you run it more than once in 45 days,
         * customers will get another email
         *
        */

        $secondChance = new Bloom_SecondChanceEmail_Model_Observer();
        $secondChance->sendSecondChanceEmails();

    }

}

$shell = new Mage_Shell_secondAttemptSendInvite();
$shell->run();

 

Now to get this to run, you use ssh and log into your site, chance into the shell directory

$ cd shell/ ( hit enter )

then type this command

$ php secondChanceEmail.php ( hit enter )