magento and ajax
http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-3-magento-controller-dispatch
Good tutorial
http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-3-magento-controller-dispatch
Good tutorial
If your on the checkout/cart page, you can get the shipping totals:
$shipping_total = $this->getQuote()->getShippingAddress()->getShippingAmount();
After you ssh into server:
$ vi /etc/passwd
You should see something similar to
bloom:x:502:503::/var/www/vhosts:/bin/bash
devuser:x:48:505::/home/devuser:/bin/bash
bloomcom:x:503:506::/var/www/vhosts:/bin/bash
Just change the part where is says: /var/www/vhosts
to whatever folder you want
$ df -h ( hit enter )
Will return something similar to:
Filesystem Size Used Avail Use% Mounted on /dev/sda5 128G 80G 47G 64% / /dev/sda2 2.0G 264M 1.6G 15% /tmp /dev/sda1 99M 23M 71M 25% /boot tmpfs 16G 0 16G 0% /dev/shm
After logging in to your server via ssh:
$ find / -type f -printf "%s %h/%f\n" | sort -rn -k1 | head -n 50 | awk '{ print $1/1048576 "MB" " " $2}' ( hit enter )
Edit PHP config file: /etc/php.ini
$ sudo nano /etc/php.ini
Do a search for pdo_mysql_default
In nano, type <control button> and press W
type in pdo_mysql_default and hit enter
Change to
pdo_mysql.default_socket=/tmp/mysql.sock
Restart apache:
$ sudo apachectl restart
Taken from http://craigwaterman.com/2011/07/21/adding-mcrypt-to-php-on-os-x-10-7-lion/ but cleaned up a few potential gotchas:
This is a guide for those who need to install (or re-install) mcrypt under PHP in OS X 10.7 (Lion).
You’ll need the following:
phpinfo() just in case./Users/sushi/Source/lion/$ cd ~/Source/lion ( hit enter ) $ tar xvfj libmcrypt-2.5.8.tar.bz2 ( hit enter ) $ tar xvfz php-5.3.6.tar.gz ( hit enter )
Let’s configure libmcrypt for installation:
$ cd libmcrypt-2.5.8 ( hit enter ) $ MACOSX_DEPLOYMENT_TARGET=10.7 CFLAGS='-O2 -fno-common -arch i386 -arch x86_64' \ LDFLAGS='-O2 -arch i386 -arch x86_64' \ CXXFLAGS='-O2 -fno-common -arch i386 -arch x86_64' \ ./configure --disable-dependency-tracking ( hit enter )
If you get some errors, try removing a few items:
$ MACOSX_DEPLOYMENT_TARGET=10.7 CFLAGS='-O2 -fno-common' \ LDFLAGS='-O2' \ CXXFLAGS='-O2 -fno-common' \ ./configure --disable-dependency-tracking ( hit enter )
Now let’s build and install libmcrypt itself.
$ make ( hit enter ) $ sudo make install ( hit enter )
You can run make -j8 if you’re on a Quad-Core i7 and are curious how much it speeds up compilation, it makes no difference for installing mcrypt.
With libmcrypt ready to use, we need to compile the php extension for it.
$ cd ~/Source/lion/php-5.3.6/ext/mcrypt ( hit enter ) $ /usr/bin/phpize ( hit enter ) MACOSX_DEPLOYMENT_TARGET=10.7 CFLAGS='-O2 -fno-common -arch i386 -arch x86_64' \ LDFLAGS='-O2 -arch i386 -arch x86_64' \ CXXFLAGS='-O2 -fno-common -arch i386 -arch x86_64' \ ./configure --with-php-config=/Developer/SDKs/MacOSX10.7.sdk/usr/bin/php-config ( hit enter )
( You might have to hit enter again to make it execute )
If you get some errors try removing a few things like we did above:
MACOSX_DEPLOYMENT_TARGET=10.7 CFLAGS='-O2 -fno-common' \ LDFLAGS='-O2' \ CXXFLAGS='-O2 -fno-common' \ ./configure --with-php-config=/Developer/SDKs/MacOSX10.7.sdk/usr/bin/php-config ( hit enter )
$ make ( hit enter ) $ sudo make install ( hit enter )
Everything should be ready to hook up at this point, we’ll need to update /etc/php.ini to tell php to load the extension.
Verify that /etc/php.ini exists. If you’ve never worked with it before, or have just upgraded to Lion, you’ll need to copy php.ini.default to php.ini with:
# skip this step if /etc/php.ini already exists. $ sudo cp /etc/php.ini.default /etc/php.ini ( hit enter )
Update php.ini and tell php to load our newly compiled mcrypt.so
$ sudo nano /etc/php.ini ( hit enter )
Add the following to the end of the file, then save and exit:
extension=mcrypt.so
Now restart Apache:
$ sudo apachectl graceful ( hit enter )
OR
$ sudo apachectl stop ( hit enter )
THEN
$ sudo apachectl start ( hit enter )
OR using Macs typical user interface:
Verify in your phpinfo() that mcrypt is really there, it should look like this:
And that should be it
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.
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
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 |
| 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 |
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.
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 |
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 )