Magento Knowledge

piaoling  2012-07-10 09:03:18


Magento Knowledge

by Aland Hou

一,Magento 模块初始化

1magento apache服务器安装及配置

1apache,php,mysql的安装

sudo apt-get install apache2

sudo apt-get install php5

sudo apt-get install php5-curl /sudo apt-get install php-curl(php7)

sudo apt-get install phpmyadmin

sudo apt-get install mysql-server

sudo apt-get install mysql-client

sudo apt-get install subversion

sudo apt-get install flashplugin-nonfree

2)配置host

sudo gedit /etc/hosts

将以下代码加入hosts里,也可以将其他域名加入

127.0.0.1 magento.localhost

127.0.0.1 www.localhost.com

3)配置apache及虚拟机

开启重写:

sudo a2enmod rewrite


#开启本地虚拟机

sudo gedit /etc/apache2/httpd.conf

将以下代码加入httpd.conf


NameVirtualHost 127.0.0.1:80

#www.localhost.com


  ServerName www.localhost.com
  DocumentRoot "/var/www"
  DirectoryIndex index.php
 
    AllowOverride All
    Allow from All
 


# magento.localhost

  ServerName magento.localhost
  DocumentRoot "/var/www/sh-stable"
  DirectoryIndex index.php
 
    AllowOverride All
    Allow from All
 


可以按照同样方法加入多个虚拟机,无限制。

4)配置phpmyadmin

将以下代码加入etc/apache2/httpd.conf


# phpMyAdmin default Apache configuration


Alias /phpmyadmin /usr/share/phpmyadmin


Options FollowSymLinks

DirectoryIndex index.php


AddType application/x-httpd-php .php


php_flag magic_quotes_gpc Off

php_flag track_vars On

php_flag register_globals Off

php_admin_flag allow_url_fopen Off

php_value include_path .

php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp

php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/



# Authorize for setup

AuthType Basic

AuthName "phpMyAdmin Setup"

AuthUserFile /etc/phpmyadmin/htpasswd.setup

Require valid-user


# Disallow web access to directories that don't need it

Order Deny,Allow

Deny from All

Order Deny,Allow

Deny from All


可以到/etc/phpmyadmin/config.inc.php中配置用户名,密码等,一些默认配置在/usr/share/phpmyadmin/config.default.php中。


2,创建包和模块

文章中的所有样例代码可以从

http://houhuiliang.gotoip2.com/download/downloadFileAllKind.php?parth=upload/events/44/2012_07_05_13_04_1010329.tar下载,建议最好自己动手写下,能够发现些问题。


自定包和模块放在 app/code/local/your package/your module

包名和模块名首字母大写,包名一般是公司名。

模块下创建etc,controllers,Block,Model,Helper,sql文件夹

app/code/local/Alanstormdotcom/Configviewer/Block

app/code/local/Alanstormdotcom/Configviewer/controllers

app/code/local/Alanstormdotcom/Configviewer/etc

app/code/local/Alanstormdotcom/Configviewer/Helper

app/code/local/Alanstormdotcom/Configviewer/Model

app/code/local/Alanstormdotcom/Configviewer/sql

etc目录存放module的配置文件,一般有config.xml,system.xml,adminhtml.xml,api.xml,wsdl.xml等配置文件

sql目录存放module的升级脚本文件

Helper目录存放module的帮助类


1)创建一个新module,首先要在etc目录下创建配置文件config.xml

   <Alanstormdotcom_Configviewer>   0.1.0            standard    Alanstormdotcom_Configviewer  configviewer              configviewer.xml                     singleton   Alanstormdotcom_Configviewer_Model_Observer  checkForConfigRequest              Alanstormdotcom_Configviewer_Model        Alanstormdotcom_Configviewer_Model_Layout_Update             Alanstormdotcom_Configviewer_Block       


模块的Block,model,controller重写也在Moduleetc/config.xml文件中。在重写magento中会有详细讨论。


2)配置文件创建好后,要创建激活文件放在app/etc/modules/中。激活文件的命名必须是PackageName_ModuleName.xml

  true  local      3)创建controlleraction controller类名命名规则为:pagecagename_modulename_controllernameController(注意首字母大写),并继承 Mage_Core_Controller_Front_Action类(后台controller不同)。文件地址为:app/code/local/packagename/moduename/controllers/controllername 样例:                     0.2.0<!--当前版本是0.2.0,会执行升级文件中版本号不大与0.2.0的文件-->                                                              standard                                          Alanstormdotcom_Weblog                       weblog                                                                                                Alanstormdotcom_Weblog_Model               weblog_mysql4<!--weblog Model有一个资源模型weblog_mysql4,资源模型用来和数据库交互-->                        <!--weblog Model的资源模型,名称必须和resourceModel定义的相同-->                    Alanstormdotcom_Weblog_Model_Mysql4                    <!--资源实体-->                                  blog_posts
	
                                                                                      
<!--weblog
setup,用来module初始化和升级,升级文件会放在sql/weblog_setup/-->                                                  Alanstormdotcom_Weblog                           Alanstormdotcom_Weblog_Model_Resource_Mysql4_Setup                                                                         core_setup                                                                                                             core_write                                                                                            core_read                                                        


(2)IndexController.php  class Alanstormdotcom_Complexworld_Model_Resource_Eav_Mysql4_Eavblogpost extends Mage_Eav_Model_Entity_Abstract
{
    public function _construct()
    {
        $resource = Mage::getSingleton('core/resource');
        $this->setType('complexworld_eavblogpost');
        $this->setConnection(
                $resource->getConnection('complexworld_read'),
                $resource->getConnection('complexworld_write')
        );
    }
}


该类为eavblogpost的资源类,和普通类普通之处:
  • 继承的父类不同
 资源类型是普通还是Eav,在于看它的父类,Eav资源类型类一般继承 Mage_Eav_Model_Entity_Abstract,也可以继承其他以 Mage_Eav_Model_Entity_Abstract为父类的资源类;普通资源类型类继承自Mage_Core_Model_Mysql4_Abstract,或者继承以Mage_Core_Model_Mysql4_Abstract为父类的资源类。
  • 初始化需要指定实体类型,资源链接方式。
相关知识:1Magento ORM: Entity Attribute Value; Part 1 http://alanstorm.com/magento_advanced_orm_entity_attribute_value_part_1 2,深入理解Magento – 第六章 – 高级Magento模型:http://houhuiliang.gotoip2.com/bloglist.php?blogId=601 3,深入理解Magento – 第五章 – Magento资源配置:http://houhuiliang.gotoip2.com/bloglist.php?blogId=521 四,数据收集器


在我们开始介绍数据操作前,我们先介绍一个神兵利器—Varien Data Collections。在最早的时候我们写php通常用Array来做数据收集器,这个小东西可发挥了大作用,要知道如果你想在其他语言中实现Array有多么难过。
例如cc++。

php5中,更是发扬了Arrayphp内置了一些类和接口,允许你创建你自己的数据结构。Magento充分利用了这一点,在使用 Varien_Data_Collection来做数据收集的时候,它实现了php内置IteratorAggregate对象迭代器和 Countable两个接口。下面是用php内置类ArrayObject的一个例子。

$array = new ArrayObject();

class MyCollection extends ArrayObject{}

$collection = new MyCollection();

$collection[] = 'bar';

在接下来的文章中,我认为你已经了解ArrayObjectIteratorAggregateCountable。如果还是很陌生,我建议你先阅读这篇文章PHP5对象迭代(Object Iteration)。当然你不必了解很底层的东西,你只需要知道如何用就可以了。

Magento代码中,其实每个Model都有个Collection。了解这些数据收集器是如何工作的是你成为一个真正Magento开发人员的关键点。
下面让我们开始吧,前面我们创建过一个Helloworld模块,现在我们继续用他开始我们接下来的学习。

创建一个数据收集器

首先,我们创造一些新的对象。

$thing_1 = new Varien_Object();

$thing_1->setName('Richard');

$thing_1->setAge(24);


$thing_2 = new Varien_Object();

$thing_2->setName('Jane');

$thing_2->setAge(12);


$thing_3 = new Varien_Object();

$thing_3->setName('Spot');

$thing_3->setLastName('The Dog');

$thing_3->setAge(7);

Magento中所有的Model都继承Varien_Object,在面向对象编程中,这样做的好处是当你想往多个Model中添加方法的时候,你只需要简单地修改一个文件即可。

在继承Varien_Object的类中,有两个魔术方法,get/set,你可以很方便的向对象中加入一个属性(值),让我们看个例子。

var_dump($thing_1->getName());

如果你忘记了属性的名字,你可以将所有数据都获取到:

var_dump($thing_3->getData());

你将看到以下结果:

array

'name' => string 'Spot' (length=4)

'last_name' => string 'The Dog' (length=7)

'age' => int 7

注意last_name属性,是用下滑线分隔的,如果你想用getset魔术方法,那么需要使用驼峰命名法。

$thing_1->setLastName('Smith');

在新版本的magento中你可以用array关联数组的方式获取数据。

var_dump($thing_3["last_name"]);

T这个归功于php5的新特性,ArrayAccess接口。也是 “Object Oriented Programming”.

现在然我们把这些对象加到数据收集器Varien_Data_Collection中。很多程序员将Collection看成是数组,当然我不反对。

$collection_of_things = new Varien_Data_Collection();

$collection_of_things

->addItem($thing_1)

->addItem($thing_2)

->addItem($thing_3);

大多数Magento data Collections继承于Varien_Data_Collection,你可以使用里面的任何一个方法。

那么我们可以做些什么呢?接下来我们使用foreach去循环它。

foreach($collection_of_things as $thing)

{

var_dump($thing->getData());

}

这里还有方法取出第一个数据和最后一个数据。

var_dump($collection_of_things->getFirstItem());

var_dump($collection_of_things->getLastItem()->getData());

将你的数据转成xml

var_dump( $collection_of_things->toXml() );

只像取某一个字段

var_dump($collection_of_things->getColumnValues('name'));

Magneto还给我们提供了一些基本的过滤功能

var_dump($collection_of_things->getItemsByColumnValue('name','Spot'));

模型数据收集器(Model Collections

前面我们有提到,所有Magento的模型数据收集器都继承Varien_Data_Collection,所以理论上我们可以使用之前的所有方法。下面让我们以product模型实战下。

public function testAction()

{

$collection_of_products = Mage::getModel('catalog/product')->getCollection();

var_dump($collection_of_products->getFirstItem()->getData());

}

基本所有的Magento模型都有个方法叫getCollection默认情况下,它会返回系统中所有的数据。

Magento的数据收集器Collection包含很多复杂的逻辑来处理数据,无论是否使用索引或缓存、EAV表等。

上面的产品数据收集器,它里面还有Varien_Data_Collection_Db类。这个类给你很多有用的方法,例如如果你输出sqlselect语句。

public function testAction()

{

$collection_of_products = Mage::getModel('catalog/product')->getCollection();

var_dump($collection_of_products->getSelect()); //might cause a segmentation fault

}

上面的方法将输出

object(Varien_Db_Select)[94]

protected '_bind' =>

array

empty

protected '_adapter' =>

...

从上面可以看出,Magento使用的是ZendFramework的数据库链接层,我们可以使用zend_db_select类中的所有方法。

接下来让我们看看更有意义的东西

public function testAction()

{

$collection_of_products = Mage::getModel('catalog/product')->getCollection();

//var_dump($collection_of_products->getSelect()); //might cause a segmentation fault

var_dump(

(string) $collection_of_products->getSelect()

);

}

上面的方法将输出

'SELECT `e`.* FROM `catalog_product_entity` AS `e`'

有时也会比较复杂,例如

string 'SELECT `e`.*, `price_index`.`price`, `price_index`.`final_price`, IF(`price_index`.`tier_price`, LEAST(`price_index`.`min_price`, `price_index`.`tier_price`), `price_index`.`min_price`) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_entity` AS `e`

INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0'

这个差异取决于你选择的字段,同样也涉及到索引和缓存。如果你看过之前的文章,那么你应该知道很多Magento表是使用Eav表结构的,默认情况 下一个eav的数据收集器将不会包含所有的对象字段,你可以通过addAttributeToSelect来添加它们。让我们看看例子。

$collection_of_products = Mage::getModel('catalog/product')

->getCollection()

->addAttributeToSelect('*'); //the asterisk is like a SQL SELECT *

或者你也可以只选某一个字段

//or just one

$collection_of_products = Mage::getModel('catalog/product')

->getCollection()

->addAttributeToSelect('meta_title');

或者更多

//or just one

$collection_of_products = Mage::getModel('catalog/product')

->getCollection()

->addAttributeToSelect('meta_title')

->addAttributeToSelect('price');

延迟加载(Lazy Loading

一般情况下,我们在创建sql后需要立刻执行,从而获取数据,例如。

$model = new Customer();

//SQL Calls being made to Populate the Object

echo 'Done'; //execution continues

但是Magento不是这样的,它采用的是Lazy Loading。延迟加载意味着在程序需要数据前,sql是不执行的,如下。

$collection_of_products = Mage::getModel('catalog/product')

->getCollection();

在这个时候Magento还没有链接数据库,你可以放心地去做你想要做的事。

$collection_of_products = Mage::getModel('catalog/product')

->getCollection();

$collection_of_products->addAttributeToSelect('meta_title');

你不必担心每次添加属性的时候Magento都会执行一个sql,去获取数据,sql只有在你需要数据的时候才会被执行。

Magento对数据库连接层做了良好的封装,当然它也考虑到了效率问题。在一般情况下,你没必要去担心sql后台是怎么执行的,只需要专心做你的功能,例如区块、布局等。这是Magento非常优秀的地方。

过滤数据(Filtering Database Collections

最重要的一个方法是addFieldToFilter。通过这个方法可以添加我们sql中的WHERE语句。

public function testAction()

{

$collection_of_products = Mage::getModel('catalog/product')

->getCollection();

$collection_of_products->addFieldToFilter('sku','n2610');

 

//another neat thing about collections is you can pass them into the count //function. More PHP5 powered goodness

echo "Our collection now has " . count($collection_of_products) . ' item(s)';

var_dump($collection_of_products->getFirstItem()->getData());

}

addFieldToFilter方法中的第一个参数是你想过滤的字段名称,第二个是你想过滤的值。例如刚刚sku是字段名称,n2610是值。

第二个参数也可以被用来指定某一类型的数据。稍微有些复杂,我们继续往下看。

$collection_of_products->addFieldToFilter('sku','n2610');

这个等同于sql中的where条件句

WHERE sku = "n2610"

下面的例子自己尝试下

public function testAction()

{

var_dump(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addFieldToFilter('sku','n2610')

->getSelect());

}

将会输出这个

SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'

但是这个很快会变得很复杂。试着做下面的练习。

var_dump(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addAttributeToSelect('*')

->addFieldToFilter('meta_title','my title')

->getSelect()

);

输出的将是下面的sql语句。

SELECT `e`.*, IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) AS `meta_title`

FROM `catalog_product_entity` AS `e`

INNER JOIN `catalog_product_entity_varchar` AS `_table_meta_title_default`

ON (_table_meta_title_default.entity_id = e.entity_id) AND (_table_meta_title_default.attribute_id='103')

AND _table_meta_title_default.store_id=0

LEFT JOIN `catalog_product_entity_varchar` AS `_table_meta_title`

ON (_table_meta_title.entity_id = e.entity_id) AND (_table_meta_title.attribute_id='103')

AND (_table_meta_title.store_id='1')

WHERE (IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) = 'my title')

在你有空的时候可以好好研究下上面的sql语句,我们先不转移焦点,继续我们下面的讲解。

其它比较运算符

我确定在刚刚的练习中,你想知道如何实现一个不是“=”的where条件句,例如不等于、大于、小于。刚刚我们有讲过addFieldToFilter的第二个参数允许传入不同“类型”。
其实很简单,只要将一个简单的数组作为第二个参数传入addFieldToFilter方法就可以变换条件句。

数组的键就是“类型”,关联的值就是你想过滤的值。我们改写下上面的代码。

public function testAction()

{

var_dump(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addFieldToFilter('sku',array('eq'=>'n2610'))

->getSelect()

);

}

看上面的过滤器

addFieldToFilter('sku',array('eq'=>'n2610'))

正如你看到的,第二个参数是一个php的数组。它的键是“eq”,代表等于的意思。

Magento在这个函数中有一系列英语的缩写,这些词的资料可以参考tear of remembrance。这些沿用了Perl语言中的一些比较运算符号。

在这里我将Magento所有的条件判断符号列出来供大家参考。

array("eq"=>'n2610')

WHERE (e.sku = 'n2610')

 

array("neq"=>'n2610')

WHERE (e.sku != 'n2610')

 

array("like"=>'n2610')

WHERE (e.sku like 'n2610')

 

array("nlike"=>'n2610')

WHERE (e.sku not like 'n2610')

 

array("is"=>'n2610')

WHERE (e.sku is 'n2610')

 

array("in"=>array('n2610'))

WHERE (e.sku in ('n2610'))

 

array("nin"=>array('n2610'))

WHERE (e.sku not in ('n2610'))

 

array("notnull"=>'n2610')

WHERE (e.sku is NOT NULL)

 

array("null"=>'n2610')

WHERE (e.sku is NULL)

 

array("gt"=>'n2610')

WHERE (e.sku > 'n2610')

 

array("lt"=>'n2610')

WHERE (e.sku < 'n2610')

 

array("gteq"=>'n2610')

WHERE (e.sku >= 'n2610')

 

array("moreq"=>'n2610') //a weird, second way to do greater than equal

WHERE (e.sku >= 'n2610')

 

array("lteq"=>'n2610')

WHERE (e.sku <= 'n2610')

 

array("finset"=>array('n2610'))

WHERE (find_in_set('n2610',e.sku))

 

array('from'=>'10','to'=>'20')

WHERE e.sku >= '10' and e.sku <= '20'

其中大多数是自我的理解,但有几个得特别注意。

in, nin, find_in_set

in and nin 条件句中,语序你传入一个数组作为值。例如:

array("in"=>array('n2610','ABC123')

WHERE (e.sku in ('n2610','ABC123'))

notnull, null

关键字NULL是最特殊的sql句,它将忽略你传入的值。

array("notnull"=>'n2610')

WHERE (e.sku is NOT NULL)

from – to 过滤

这是另一种过滤方式,在传入的数组中,允许你传入两个键,是从哪里到哪里的意思,一个数值区间。

public function testAction

{

var_dump(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addFieldToFilter('price',array('from'=>'10','to'=>'20'))

->getSelect()

);

}

上面等同于

WHERE (_table_price.value >= '10' AND _table_price.value <= '20')

AND 或者 OR

根据刚才讲的内容,你可以知道,通过多个 addFieldToFilter方法可以获得一个”AND”的条件句。

function testAction()

{

echo(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addFieldToFilter('sku',array('like'=>'a%'))

->addFieldToFilter('sku',array('like'=>'b%'))

->getSelect()

);

}

等同于下面的子句

WHERE (e.sku LIKE 'a%') AND (e.sku LIKE 'b%')

但是,聪明的你可以发现,上面的例子不可能返回任何结果,因为一个sku不可能以a开头,同时也以b开头。
我们希望用的应该是”OR”,那么如何实现呢?这又使我们将焦点集中到了addFieldToFilter方法的第二个参数上。

如果你希望构造一个or的语句,首先我们构造两个参数。

public function testAction()

{

$filter_a = array('like'=>'a%');

$filter_b = array('like'=>'b%');

}

然后将它们作为一组参数传入addFieldToFilter方法中,如下。

public function testAction()

{

$filter_a = array('like'=>'a%');

$filter_b = array('like'=>'b%');

echo(

(string)

Mage::getModel('catalog/product')

->getCollection()

->addFieldToFilter('sku',array($filter_a,$filter_b))

->getSelect()

);

}

你可以看到这样的一个子句。

WHERE (((e.sku LIKE 'a%') OR (e.sku LIKE 'b%')))

另一种or

$attributeA = array('attribute'=>'sku','like'=>'%i%');

$attributeB = array('attribute'=>'name','like'=>'%i%');

$collection = Mage::getModel('catalog/product')->getCollection()->setStoreId(1)

->addAttributeToSelect("*")

->addAttributeToFilter(array($attributeA,$attributeB));

echo $collection->getSelect()->__toString();

你可以得到这样的一个子句:

WHERE ((e.sku like '%i%') OR (IF(_table_name.value_id > 0, _table_name.value, _table_name_default.value) like '%i%'))


相关知识:

1Varien Data Collectionshttp://alanstorm.com/magento_collections

2,深入理解Magento-第十章-数据操作&数据收集器:http://houhuiliang.gotoip2.com/bloglist.php?blogId=527

3Using Collections in Magentohttp://houhuiliang.gotoip2.com/bloglist.php?blogId=609


五,MagentoMage.phpApp.php Mage.php: DS    / PS BP    magento根目录getVersion getVersionInfo  reset 将所有静态数据恢复之默认值register 注册一个静态变量unregister 注销静态变量registry 获取静态变量setRoot 设置mangento根目录的绝对路径getRoot 获取mangento应用程序根目录的绝对路径,var/www/magento/app/ getEvents 获取所有事件objects 获取mangento根目录的绝对路径getBaseDir 获取mangento根目录的绝对路径,var/www/magento/ getModuleDir 获取module的绝对路径getStoreConfig 获取store配置信息getStoreConfigFlag 获取store配置flag getBaseUrl 获取基本URL getUrl
getDesign 获取设计包model getConfig 获取配置实例addObserver 添加事件监听者dispatchEvent 分发事件getModel 获取model,最常用getSingleton 获取单例getResourceModel 获取资源model getControllerInstance 获取控制器实例getResourceSingleton 获取资源单例getBlockSingleton helper 获取helperexception throwException
app 获取初始化应用对象init 初始化应用run isInstalled
log
logException
setIsDeveloperMode
getIsDeveloperMode
printException
getScriptSystemUrl
setIsDownloader 以上方法可以在任何地方(controller,block,template,model)里使用,例如:Mage::getStoreConfig($path); App.php __construct init
baseInit
initSpecified
run
getCookie 获取cookie reinitStores
isSingleStoreMode
setCurrentStore 设置当前store setErrorHandler
loadArea
loadAreaPart
getArea
getStore 获取当前store对象getSafeStore getStores 获取store数组getDefaultStoreView getDistroLocaleCode
getWebsite 获取当前网站getWebsites 获取网站数组getGroup getLocale 获取本地化对象getLayout 获取layout getTranslator
getHelper
getBaseCurrencyCode 获取货币code getConfig		
getFrontController 获取前端控制器getCacheInstance 获取缓存实例getCache 获取缓存数据loadCache 加载缓存saveCache 保存缓存removeCache 移除缓存cleanCache 清除缓存,并触发application_clean_cache事件useCache 判断缓存类型是否可用saveUseCache cleanAllSessions 清楚所有session getRequest 获取请求对象getResponse 获取响应对象addEventArea dispatchEvent
setUpdateMode
getUpdateMode
throwStoreException
setUseSessionVar
getUseSessionVar
getAnyStoreView
setUseSessionInUrl
getUseSessionInUrl
setIsSingleStoreModeAllowed
getGroups
isInstalled
getUseCacheFilename
prepareCacheId 以上方法可以在任何地方(controller,block,template,model)里使用,例如:Mage::app()->getStore(); 六,MagentoLayouttemplate magento默认使用的layoutfrontend/base/default/layout,可以在后台为各个store设置不同的theme,也可以设置在不同的时间段内使用不同的theme所有的modulelayout都是从page.xml开始,通过在moduleconfig.xml中设置更新layout的文件,如:         catalog.xml         catalog.xml中可以更新,删除,添加page.xml或其他文件的default配置。样例:"label" module="page">  All Pages  "page/html" name="root" output="toHtml" template="page/3columns.phtml">  "page/html_head" name="head" as="head">  "addJs">   "page/js_cookie" name="js_cookies" template="page/js/cookie.phtml"/>  "addCss">css/styles.css  "addItem">skin_csscss/styles-ie.csslt IE 8  "addCss">css/widgets.css    "core/text_list" name="after_body_start" as="after_body_start" translate="label">  Page Top   标签default 标签定义的layout在所有页面都会加载,一个页面加载哪些layout是由handler定义的。一般一个页面会加载default,frontname_controllername_actionname,STORE_currentStoreCode,THEME_frontend_yourPackage_yourTheme 具体加载了哪些handler可以用alanstorm上的layoutview查看。标签block标签定义了将一个模块加载到layout里。一般有name,as,templatetype属性。nameblock的名字,可以用来获取block.,getBlock(block name)等。asblock名称的别名,又叫缩写,可以简化block名称。在父block调用子block时,可以通过getChildBlock(alias)template:为block设置模板,也可以在block里通过$this->setTemplate(template.phml)设置。type:定义block的类型output:一般一个theme里只有一个根block含有output属性,用来定义html起始输出。标签action一般和属性method一起使用,用来为block设置一些基本配置数据。其中methodblock中的方法。标签可以用来更新,添加,删除已有的blcok的数据。标签将已有的block移除标签handle属性同时使用,可以将其他handlelayout加载到当前layout。在一些block或其他内容在多个handle里都要使用时,可以新建一个共有的handle,将需要多次使用的block放到共有handle里,在通过update标签,就可以加载这些多次使用的blcok七,MagentoBlock 一般一个新的block都继承magnto核心的block类:Mage_Core_Block_Template,或者继承以Mage_Core_Block_Template为父类的类。 Mage_Core_Block_Template继承 Mage_Core_Block_Abstract 1,常用methodssetTemplate:为blcok设置模板,也可以在layout中设置,有些layout没有定义template,很有可能是在block_construct方法中自定义了。getBaseUrl:获取store的基本urlgetJsUrl:获取js的基本urlgetSkinUrl:获取皮肤的基本urlgetRequest:获取http请求对象。append:将block添加到另一个block中。getAction:获取actiongetBlockAlias:获取block的别名getChildHtml:获取子blockhtml内容getHelper:获取helpersetAttribute:为block设置属性和值。toHtml:获取blockhtml内容。__():翻译方法2,重写block 在你moduleetc/config.xml中,添加以下代码:                                                                yourPackage_yourModule_Block_yourBlock                                         如果你有更多的目录层级,可以用下滑线来分隔。例 如:       App_Catalog_Block_Category_View       在这个例子中,我们重写了app/code/core/Mage/Catalog/Block/Category/View.php在你重写的block中,一般都要继承原来的blcok,只需要在新block中添加需要修改的方法即可。3tips 模板或block中创建一个blcok方法Mage::getSingleton('core/layout')->createBlcok(type);或者$this->getLayout()->createBlock(); 使用cms blockMage::getSingleton('core/layout')->createBlcok('core/cms')->setBlockId(cms block id); 或者$this->getLayout()->createBlock('cms/block')->setBlockId(cms block id); 八,MagentoModel 一个自定义的model一般都要继承 Mage_Core_Model_Abstract,或者继承以 Mage_Core_Model_Abstract为父类的类。该类继承Varien_Object,支持setData,getData等方法。1,常用方法:delete:加载一个实例后,通过delete,可以删除该实例。getCollection:获取对象collection集合。getResource:获取数据库资源对象。save:保存对象。load:加载实例。获取model方法:Mage::getModel(uri);Mage::getSingleton(uri); 2,tips: 通过$resource = Mage::getSingleton('core/resource')->getConnection('core_read'); $resource->query($sql); 或者$resource->fetchAll($sql); 直接运行sql3,重写model 重写核心model或其他人的model,在你/etc/config.xml中添加类似如下代码:         yourPackage_yourModule_Model_Customer         这样就重写了Mage_Core_Customer_Model_Customer模型到 yourPackage_yourModule_Model_Customer九,Magentocontroler 自定义的controler一般都继承Mage_Core_Controller_Front_Action,该类继承Mage_Core_Controller_Varien_Action1,常用方法loadLayout:加载相关的layout readerLayout:渲染layout,输出html等。getRequest:获取请求对象,对象中包含请求参数等信息。GetResponse:获取响应对象。2,重写核心controller etc/config.xml中加入类似如下代码:                /shopping/cart/       这样就把 整个controllercheckout/cart重写到了 shopping/cartNotice:控制器不会自动加载,所以我们需要包含文件,这里与区块(Block)不一样在你的controller里需要包含重写的controller,并继承他。require_once 'Mage/Checkout/controllers/CartController.php' 另外一种重写方法:同样是在etc/config.xml中:          App_Mycms/index  true    App_Mycms/index/noroute             这样就把controlleractioncms/index/noroute重写到了 App_Mycms/index/noroute还有一种是同名覆盖的,除非没有以上两种办法重写才使用。同名覆盖:app/local/中,将核心的module复制过来,存放地址如下:app/local/Mage/Core/controller/Front/Action.php 这样就可以覆盖掉mogento核心的Action.php同样可以覆盖block,model,helper等,这是在以上重写方法不支持的情况下才做的事。十,MagentoSEO 1magento后台SEO优化的基本步骤:step one:打开URL优化开关,让magento以更好看,更友好的URL形式展现。看下图:

step two:将选好的关键字尽可能多的暴露在magento站点上的所有页面的title,meta,h1上,当然要尽可能的友好哟,不要太机械。

default title设定了magento中各个页面的默认的title,也就是当程序(员)在某个magento页面中没有指定的时候就会显示这边设置了的title,这样就不浪费任何一个机会来暴露关键字其它的两个title,无论是prefix还是sufix,其功能是设定magento各页面的title前缀和后缀都是为了加大关键字的曝光率。Default Description Default Keywords 这两个选项设置的效果是在每个页面中添加 meta,当然是在程序(员)没有设置的时候默认设置的值。
    
Default Robots指定spider的工作行为。Miscellaneous scripts magento 提供这个的用武之地我觉得除了放置google的分析代码之类之外,还有一个妙用就是我们可以在这里放置h1标签。在这里放h1的一 个好处是它是直接跟在body标签之后的,这个位置本身就已经是优势了。不过最后不要太简单就放了h1,搜索引擎还会考虑在h1周边的文本的。如果不希望 在页面上显示可以用css将其隐藏。要知道搜索引擎的sipdercrawler在工作时就像我们早期使用的文本浏览器,是完全忽略掉jscss的, 所以你对用户虽说是隐藏的,但是spider能读取到。这个设置是在所有的magento页面都有效的。step three:优化页面的底部,关键字要尽量的突显在页面的开始和结尾部分,就像我们写文章一样,首尾呼应,开头主题鲜明,结尾再次强调。

你完全可以在copyright中放入和关键相关的语句,再把它隐藏。虽然用户看不到,不过spider会看到的。Miscellaneous HTML似乎相对来说位置更重要,也可以放和关键这相关的内容,根据实际情况看看要不要隐藏。如果要放js代码之类的要注意哟,要放在前面,把后面的位置留给关键字。Logo Image Alt也不要放过哟!!step four:magento中发布产品时,好好描述,充分利用Name , Meta Title,Meta Description,Short Description * 

step five:在向magento上传产品图片时,要给图片添加lable.要不然程序(员)也只能是巧妇难为无为之炊啊。

step six:magento添加product tag 

step seven:将我的magento站点的URL加上html后缀。搜索引擎毕竟不是人,所以更多的时候搜索引擎不喜欢访问动态页面,因为解析有可能出错,加上html后缀使得页面更有可能被spider爬行。

2MAGENTO robots.txt设置# $Id: robots.txt,v magento-specific 2010/28/01 18:24:19 goba Exp $ # # robots.txt # # This file is to prevent the crawling and indexing of certain parts # of your site by web crawlers and spiders run by sites like Yahoo! # and Google. By telling these "robots" where not to go on your site, # you save bandwidth and server resources. # # This file will be ignored unless it is at the root of your host: # Used:    http://example.com/robots.txt # Ignored: http://example.com/site/robots.txt # # For more information about the robots.txt standard, see: # http://www.robotstxt.org/wc/robots.html # # For syntax checking, see: # http://www.sxw.org.uk/computing/robots/check.html # Website Sitemap Sitemap: http://www.mydomain.com/sitemap.xml # Crawlers Setup User-agent: * Crawl-delay: 10 # Allowable Index Allow: /*?p= Allow: /index.php/blog/ Allow: /catalog/seo_sitemap/category/ Allow:/catalogsearch/result/ # Directories Disallow: /404/ Disallow: /app/ Disallow: /cgi-bin/ Disallow: /downloader/ Disallow: /includes/ Disallow: /js/ Disallow: /lib/ Disallow: /magento/ # Disallow: /media/ // I would personally allow this folder for google product caching Disallow: /pkginfo/ Disallow: /report/ Disallow: /skin/ Disallow: /stats/ Disallow: /var/ # Paths (clean URLs) Disallow: /index.php/ Disallow: /catalog/product_compare/ Disallow: /catalog/category/view/ Disallow: /catalog/product/view/ Disallow: /catalogsearch/ Disallow: /checkout/ Disallow: /control/ Disallow: /contacts/ Disallow: /customer/ Disallow: /customize/ Disallow: /newsletter/ Disallow: /poll/ Disallow: /review/ Disallow: /sendfriend/ Disallow: /tag/ Disallow: /wishlist/ # Files Disallow: /cron.php Disallow: /cron.sh Disallow: /error_log Disallow: /install.php Disallow: /LICENSE.html Disallow: /LICENSE.txt Disallow: /LICENSE_AFL.txt Disallow: /STATUS.txt # Paths (no clean URLs) Disallow: /*.js$ Disallow: /*.css$ Disallow: /*.php$ Disallow: /*?p=*& Disallow: /*?SID= 十一,Magento之性能优化1.压缩js,css代码,如果有必要把所有的css,js分别综合到一个文件中,并压缩缓存.可以开启magento自身的merge功能。2.清除magento模板中不必要的注释,为所使用到的图片瘦身. 3.优化magento代码,这个步骤工作量大,但可能是效果显著的步骤,不过前提是你非常熟悉magento,彻底删除不用的模块,关闭没用的 block, 清除无效,无用的xml(解析xml非常昂贵的),在一个页面中尽量不要大量调用magentoimage resize功能,非常消耗内存,除非你自己优化代码。4.mysql配置优化,充分发挥你的硬件资源,下面的数值要根据你的配置调整: key_buffer_size = 512M
max_allowed_packet = 64M
table_cache = 512
sort_buffer_size = 4M
net_buffer_length = 8K
read_buffer_size = 4M
read_rnd_buffer_size = 2M
myisam_sort_buffer_size = 64M
tmp_table_size = 128M
query_cache_size = 96M
query_cache_type = 1
thread_cache_size = 8
max_connections = 400
wait_timeout = 300
5.magentovar目录挂载到内存中,加快读取速度(这个特别推授) mount -t tmpfs -o size=100M,mode=0777 tmpfs var
6.修改 .htaccess mod_deflate 配置php_flag zlib.output_compression on AddHandler application/x-httpd-php5 .css # Insert filter on all content SetOutputFilter DEFLATE # Insert filter on selected content types only #AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript # Netscape 4.x has some problems... BrowserMatch ^Mozilla/4 gzip-only-text/html  # Netscape 4.06-4.08 have some more problems BrowserMatch ^Mozilla/4.0[678] no-gzip  # MSIE masquerades as Netscape, but it is fine BrowserMatch MSIE !no-gzip !gzip-only-text/html  # Don't compress images SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary  # Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary 7.安装php加速器,APCXCACHE,eAccelerator,具体配置可以在网上找参考,这里就不提供给大家了. 8.magentoapache中所需要的模块: mod_authz_host.so
mod_expires.so
mod_deflate.so
mod_mime.so
mod_dir.so
mod_rewrite.so     这个模块很重要,当设置Magento地址重写时,要用到mod_log_config.so libphp5.so         如果你用的是php4,那就得改成libphp4.so 9.magento标准的php配置extension=bcmath.so extension=curl.so
extension=dom.so
extension=gd.so
extension=mcrypt.so
extension=memcache.so
extension=mhash.so
extension=pdo.so
extension=pdo_mysql.so
extension=mysql.so
extension=xmlwriter.so 下面的一些扩展并不需要开启, 我们可以把它们关闭;;extension=dbase.so ;;extension=json.so
;;extension=mysqli.so
;;extension=pdo_sqlite.so
;;extension=sqlite.so
;;extension=wddx.so
;;extension=smlreader.so
;;extension=xsl.so
;;extesnion=zip.so 当然事无绝对,当你的系统环境需要某个扩展时,可以按照需要开启. 十二,Magento之数据库一些常用的数据表:产品库存类:cataloginventory_stock_item 存放产品的详细库存信息cataloginventory_stock_status 存放产品的主要库存信息cataloginventory_stock_status_idx 存放产品的主要库存信息,reindex时会根据前两个表根新数据cataloginventory_stock_status_tmp 存放index的临时数据信息,reindex完成之后会清空目录类catalog_category_entity 目录主表catalog_category_entity_datetime  catalog_category_entity_decimal catalog_category_entity_int catalog_category_entity_text catalog_category_entity_varchar catalog_category_flat_store_1 目录flat表,也就是getCollection时,数据的来源基本表,每个store对应一张表,最后的数字为storeId catalog_category_flat_store_2 catalog_category_flat_store_3 catalog_category_product 目录-产品对应表catalog_category_product_index	reindex时会根据catalog_category_product更新数据产品类catalog_product_entity 产品主表catalog_product_entity_datetime  catalog_product_entity_decimal  catalog_product_entity_gallery 可能已经废弃catalog_product_entity_int  catalog_product_entity_media_gallery 产品图片表catalog_product_entity_media_gallery_value  catalog_product_entity_text  catalog_product_entity_tier_price  catalog_product_entity_varchar  catalog_product_flat_1 产品flat表,也就是getCollection时,数据的来源基本表,每个store对应一张表,最后的数字为storeId catalog_product_flat_2  catalog_product_flat_3  catalog_product_index_eav 产品eav实体属性值表catalog_product_index_eav_idx 产品eav实体属性值index产品关系表catalog_product_link 关系主表catalog_product_link_attribute 关系属性表catalog_product_link_attribute_decimal  catalog_product_link_attribute_int  catalog_product_link_attribute_varchar  catalog_product_link_type 关系类型表,upsell,bestsellcrosssell
                     




Cmscms_block 					blcok数据表cms_block_store 				block-store对应表cms_page 					pagecms_page_store					page-store对应表Eaveav_attribute 属性表eav_attribute_group 属性分组表eav_attribute_label 属性标签eav_attribute_option 对应属性为select multiselect的属性eav_attribute_option_value 对应属性为select multiselect的属性eav_attribute_set  eav_entity_type 实体类型表eav_entity_attribute 实体属性对应表其他表就不写了。最后来一张mgento数据库关系超清晰关系图:http://houhuiliang.gotoip2.com/download/downloadFileAllKind.php?parth=upload/events/44/2012_07_06_16_26_5549564.pdf 文件格式为pdf的,里面有详细介绍。十三,其他1magento cron 计划任务(cron job)是Magento系统中一个很有用甚至可以说必须使用的功能,而最近在网上跟人聊天发现很多Magento的使用者不知道这个功能或者知道却认为可有可无,我在这里建议各位Magento的使用者,把这个功能使用起来吧。在之前关于Newsletter的那篇博文我有讲到,要使新闻能按设定的时间自动发送,就必须设置好计划任务(cron job)。计划任务(cron job)简单的来说就是在系统中每隔一段时间来重复操作一件事,比如每隔多少时间清理日志,比如每天提交Sitemapgoogle等等。而要设置计划任务(cron job),需要在网站运行的服务器(以linux为例)写一段脚本来定时调用网站根目录下的cron.php文件。下面是我自己使用的服务器的设置方式:
  1. crontab */5 * * * * /usr/bin/php -f /home/yourdomainname/public_html/cron.php   
   linux crontab查看命令: crontab -u user -l  编辑命令: crontab -u user -e          当然,首先你的服务器得支持cron job你才能使用crontab 这个命令,设置完的效果是服务器每隔5分钟运行一次你的网站根目录下的cron.php文件,cron.php运行时会去检查计划任务时间表中哪些任务的 预定时间已经到了,如果到了就立即执行预定的任务,比如提交sitemap,并同时根据各个任务的配置文件或预先设定的任务(特指newsletter) 生成新的计划任务时间表。储存这些数据的是数据库中的cron_schedule表,进这个表你会看到一个计划任务的列表         要让某个功能按时运行需要在对应的config.xml中设置计划任务,指定要运行的某个类的某个方法,同样以google sitemap为例         view plain
  1.    
  2.           
  3.               
  4.                   
  5.                    sitemap/observer::scheduledGenerateSitemaps   
  6.                   
  7.               
  8.           
  9.       
         你可以在Sitemap/Model/Observer.php文件中找到scheduledGenerateSitemaps这个方法,这个方法的作 用就是向google提交sitemap。同理当你自己的模块有需要定时运行的功能是,可以参照sitemap在自己的config.xml配置要执行的 方法。        Magento系统在你安装完毕后就已经自带了不少计划任务,在后台可以看到一些对计划任务的配置项,以sitemap为例          可以选择是否开启sitemap提交并选择提交的频率。           1.4为例,Magento自带的计划任务包括刷新分类索引,应用价格规则,更新汇率,清理日志,发送Newsletter,发送商品提醒(价格变动和库存变化)和提交google sitemap等等。            所以下次再发现功能不能用比如设置的价格规则第二天失效了等,想一下自己是否忘了给网站设置了计划任务(cron job)。2magento reindex命令方式当产品较多时,使用后台的reindex会很慢,而且会影响前台性能,这种情况下,可以自己写个脚本,并添加到cron计划中,在访问较少的情况下,如凌晨34点,让系统自动执行reindex脚本可以参考shell/indexer.php 也可以手动执行命令的方式,立即执行index命令方式如下:/usr/bin/php /var/www/magento/shell/indexer.php -reindex all  这种会重新索引所有的index,当然也可以选择性的索引某些index /usr/bin/php /var/www/magento/shell/indexer.php -reindex catalog_category_flat,catalog_category_product 这种情况下只会索引目录flat表,目录产品表。3,Magento Events 当你需要扩展Magento的核心的功能时有两个选择
  • 重写(override)Magentocore classes 
  • 使用Magentoevent-driven 机制 
由于你只能重写一次Magentocore classes(如果你需要在多个module中重写相同core class就会出现错误),所以使用MagentoEvent就大显神威了,它使得你的工作简便的简易方便。Magentoevent-driven机制中有两个非常重要的概念
  • 分发(dispatch)一个事件(event) 
  • 捕捉(catch)一个事件(event) 
Dispatching events Magento中你需要调用 Mage::dispatchEvent(...) 就可以Dispatch一个Event,   
  1. Mage::dispatchEvent('custom_event', array('object'=>$this));    
 该方法有两个参数,一个是事件的标识符(在所有事件中唯一)和一个关联数组。该数组的键值是一个dataVarien_Event_Observer 的一个实例),这个data将被执行事件的函数(observer)进行处理并返回结果。 Catching events  捕捉事件比分发复杂一些,你必须使用一个已有的module或者新建一个module.这里新建一个,config.xml文件中,我们新定义一个event observer,下面是参考示例(当然你可以定义不同scopeevent observer): Xml代码  
  1.    
  2.           
  3.            
  4.               
  5.             model    
  6.             baobazacustommodule/observer    
  7.             customObserverAction     
  8.                 
  9.              
  10.            
  11.          
  12.     
  上面的xml的配置有一个要注意的地方,就是标签里的值可以是model,object,singleton,其中modelobject是等效的且它们都将使用 Mage::getModel(....)方法来进行初始化;而singleton将使用Mage::getSingleton(....)来初始化。此 外,在Observer.php中就是相关的observer类的定义,该类既不需要继承其他类也不需要继承其他接口。这需要在 customObserverAction方法的参数中传入Varien_Event_Observer类的一个实例,正是这个实例对象把 dispatcherevent handler联系到一起。同时该实例对象也是继承于Varient_Object,所以拥有getter魔术方法,例:   
  1. class Baobaz_ACustomModule_Model_Observer   
  2. {   
  3.   public function customObserverAction(Varien_Event_Observer $observer)   
  4.   {   
  5.     $object = $observer->getEvent()->getObject(); // we are taking the item with 'object' key from array passed to dispatcher   
  6.     $object->doSomething();   
  7.    
  8.     return $this;   
  9. }    
  10.     
 Default events Magento实现了很多的events,详情参看Magento Events list 此外, Mage_Core_Model_Abstract 类默认Dispatch了一些特殊的events:
event identifier
event parameters
model_save_before
'object'=>$this
{_eventPrefix}_save_before
{_eventObject}=>$this
model_save_after
'object'=>$this
{_eventPrefix}_save_after
{_eventObject}=>$this
model_delete_before
'object'=>$this
{_eventPrefix}_delete_before
{_eventObject}=>$this
model_delete_after
'object'=>$this
{_eventPrefix}_delete_after
{_eventObject}=>$this
model_load_after
'object'=>$this
{_eventPrefix}_load_after
{_eventObject}=>$this
 {_eventPrefix} means the value of $_eventPrefix variable and {_eventObject} means the value of $_eventObject variable. All classes inheriting from Mage_Core_Model_Abstract should override these variables to create specific events being dispatched. For example for catalog cagetory these variables take following values: $_eventPrefix = 'catalog_category';  $_eventObject = 'category';   下面是一些我个人对Magento event的理解和收集的event的资料 1.其实event的原理简单,就是它在你保存或读取数据之前对一些数据进 行处理,这就是event的最终目的。所以必须得在dispatcherevent handler之间传递数据,同时该数据是以Varien_Event_Observer类形式存在,底层的实现Magento已经良好的封装,更多细节 参考Mage_Core_Model_Abstract类中的一些方法(protected  _beforeSave() protected _afterSave(),Event正是在这两方法里实现的)2.Magento中使用Event大致分为两步:
  • Binding a function to an event 
  • Implement the observer(就是function中具体实现) 
3.看下面的代码:
  1. Mage::dispatchEvent('newsletter_customer_subscribed', array('customer'=>$customer, 'email'=>$email));    
  2.    
  3. Mage::dispatchEvent('sales_order_status_change_after', array('order' => $order, 'status_before' => $status_before, 'status_after' => $status_after));    
 大家发现没有,可以在array中传递多个data(关联数组就是这样用的)


类别 :  默认(751)  |  浏览(4977)  |  评论(0)
发表评论(评论将通过邮件发给作者):

Email: