Magento是一个php电子商务系统.
内部模块化.
创建模块流程
Magento系统模块
app/code/core/Mage
其中每一个子目录都是一个单独的模块
自己创建的模块放在下面路径
app/code/local/Packagename
自创的新模块应该包含以下目录结构
app/code/local/Packagename/Configviewer/Block
app/code/local/Packagename/Configviewer/cotrollers
app/code/local/Packagename/Configviewer/etc
app/code/local/Packagename/Configviewer/Helper
app/code/local/Packagename/Configviewer/Model
app/code/local/Packagename/Configviewer/sql
接下来还需要创建两个文件
一个是config.xml
app/code/local/Packagename/Configviewer/etc/config.xml
文件内容如下
<config>
<modules>
<Packagename_Configviewer>
<version>0.1.0</version>
</Packagename_Configviewer>
</modules>
</config>
第二个文件创建在
app/etc/modules/Packagename_Configviewer.xml
此文件命名规则"包名_模块名.xml" 即"Packagename_Modulename.xml"
文件内容如下
<config>
<modules>
<Packagename_Configviewer>
<active>true</active>
<codePool>local</codePool>
</Packagename_Configviewer>
</modules>
</config>
先看看创建的模块有没有被加载出来:
1. 清空magento 缓存
2. 在后台管理界面, 进入System->Configuration->Advanced
3. 展开 "Disable Modules Output"
4. 确认 "Package_Configviewer" 显示出来了
如果看到 Package_configviewer 那么这个新模块创建成功.
创建模块逻辑
之前只是创建了模块的骨架, 现在为这个模块输入逻辑:
1. 检查 "showConfig" 查询字符串是否存在
2. 检查 "showConfig" 存在, 那么检查 "showConfigFormat" 查询字符串是否存在
3. 如果 "showConfigFormat" 存在, 那么输出指定格式的配置信息 否则输出默认格式的配置信息
4. 终止执行流程
首先config.xml文件需要修改
<config> <modules>...</modules> <global> <events> <controller_front_init_routers> <observers> <alanstormdotcom_configviewer_model_observer> <type>singleton</type> <class>Alanstormdotcom_Configviewer_Model_Observer</class> <method>checkForConfigRequest</method> </alanstormdotcom_configviewer_model_observer> </observers> </controller_front_init_routers> </events> </global> </config>
然后创建如下文件
Packagename/Configviewer/Model/Observer.php
输入以下内容
<?php class Alanstormdotcom_Configviewer_Model_Observer { const FLAG_SHOW_CONFIG = 'showConfig'; const FLAG_SHOW_CONFIG_FORMAT = 'showConfigFormat'; private $request; public function checkForConfigRequest($observer) { $this->request = $observer->getEvent()->getData('front')->getRequest(); if($this->request->{self::FLAG_SHOW_CONFIG} === 'true') { $this->setHeader(); $this->outputConfig(); } } private function setHeader() { $format = isset($this->request->{self::FLAG_SHOW_CONFIG_FORMAT}) ? $this->request->{self::FLAG_SHOW_CONFIG_FORMAT} :'xml'; switch($format) { case 'text': header("Content-Type: text/plain"); break; default: header("Content-Type: text/xml"); } } private function outputConfig() { die(Mage::app()->getConfig()->getNode()->asXML()); } }
然后清空Magento缓存, 输入URL: http://magento.example.com/?showConfig=true
显示出来的页面是巨大的XML文件, 描述了系统状态, 列出所有的模块, 数据类型, 类, 事件, 监听器, Magento会解析每个模块的config.xml, 并把他包含在这个全局配置中.
一般PHP实例化一个类是这样的:
$helper_salesrule = new Mage_Salesrule_Helper();
Magento抽象了PHP的实例化模式, 在Magento中, 上面的代码等同于
$helper_salesrule = Mage::helper('salesrule');
Magento按照以下逻辑处理:
1. 在配置文件中查找<helpers />标签
2. 在<helpers />中查找 <salesrule />标签
3. 在<salesrule /> 中查找class
4. 实例化从#3中找到的类(Mage_Salesrule_Helper)
这样看起来有些麻烦, 但好处是我们不需要更改Magento的代码就可以更改Magento的核心功能.
MVC流程:
1. URL请求被一个PHP文件拦截, 通常称为前端控制器(Front Controller)
2. 这个PHP文件分析URL, 获得一个执行控制器的名字(Action Controller)和一个执行方法(Action Method)的名字, 这个过程通常称为路由(Routing)
3. 实例化#2获得的执行控制器
4. 调用执行控制器的执行方法
5. 执行方法中处理业务逻辑, 比如获取数据
6. 执行控制器负责把数据传给显示逻辑
7. 显示逻辑生成HTML
Magento的MVC流程和这个不同:
1. URL请求被一个PHP文件拦截
2. 这个PHP文件实例化一个Magento对象
3. Magento对象实例化前端控制器
4. 前端控制器实例化全局配置中指定的路由对象, 可以是多个
5. 路由对象会逐个与请求URL匹配
6. 如果发现匹配, 那么可以获得一个执行控制器和执行方法的名字
7. 实例化#6获得的执行控制器并调用相应的执行方法
8. 执行方法中 处理业务逻辑, 数据模型
9. 控制器实例化布局对象(Layout)
10. 布局对象根据请求的参数, 系统配置创建一个块对象(Block)列表, 并实例化
11. 布局对象会调用块对象的output方法生成HTML. 这是一个递归的过程, 因为块对象可以嵌套块对象
12. 每一个块对象和一个模板文件(Template File)对应, 块对象包含了显示逻辑, 模版文件包含了HTML和PHP代码输出
13. 块对象直接从模型那里获取数据, 也就是说 Magento 的MVC 架构中, 控制器不直接把数据传给视图
创建Hello World模块
创建一个模块的目录结构
app/code/local/Test/Helloworld/Block
app/code/local/Test/Helloworld/controllers
app/code/local/Test/Helloworld/etc
app/code/local/Test/Helloworld/Helper
app/code/local/Test/Helloworld/Model
app/code/local/Test/Helloworld/sql
下面是 config.xml 的内容
PATH: app/code/local/Alanstormdotcom/Helloworld/etc/config.xml
<config>
<modules>
<Test_Helloworld>
<version>0.1.0</version>
</Test_Helloworld>
</modules>
</config>
然后我们要创建一个系统配置文件来激活这个模块 PATH: app/etc/modules/Test_Helloworld.xml <config> <modules> <Test_Helloworld> <active>true</active> <codePool>local</codePool> </Test_Helloworld> </modules> </config>
然后看看模块是否被激活
1. 清空Magento缓存
2. 在管理后台进入 System->Configuration->Advanced
3. 展开 Disable Modules Output
4. 确认Test_Helloworld显示出来了
配置路由
Magento定义路由是在config.xml中, 完善etc下面的config.xml, 增加路由信息
<?xml version="1.0" ?> <config> <modules> <Test_Helloworld> <version>0.1.0</version> </Test_Helloworld> </modules> <frontend> <routers> <helloworld> <use>standard</use> <args> <module>Test_Helloworld</module> <frontName>helloworld</frontName> </args> </helloworld> </routers> </frontend> </config>
其中frontName是路由URL的名字
为路由创建执行控制器
首先创建文件 app/code/local/Test/Helloworld/controllers/IndexController. php
class Test_Helloworld_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { echo 'Hello World!'; } }
清空缓存, 如果显示Hello world则运行正常
这个遇到一个问题搞了好久, 按照教程页面显示404, 然后加上index.php才解决
http://www.magento1800.com/index.php/helloworld/index/index
执行控制的名字构成如下
1. 以<module>标签的内容开始(Test_Helloworld)
2. 接下来一个下划线 (Test_Helloworld_)
3. 加上我们给控制器取得名字"Index" (Test_Helloworld_Index)
4. 最后加上关键词"Controller" (Test_Helloworld_IndexController)
我们自己定义的属于frontend区的执行控制器都应该继承Mage_Core_Controller_Front_Action
URL里面的index/index是什么意思
Magento的默认路由规则如下
http://www.magento1800.com/frontName/actionControllerName/actionMethod
所以我们之前的请求URL
http://www.magento1800.com/helloworld/index/index
下面3个URL是等价的
http://www.magento1800.com/helloworld/index/index
http://www.magento1800.com/helloworld/index/
http://www.magento1800.com/helloworld/
如果URL如下
http://www.magento1800.com/checkout/cart/add
Magento执行步骤如下
1. 查询全局配置, 找到frontName"checkout"对应的模块, Mage_Checkout
2. 找到执行控制器 "Mage_Checkout_CartController"
3. 调用执行控制器"addAction"方法
进一步理解执行控制器
下面我们为我们的执行控制器添加一个执行方法. 添加如下代码到IndexController.php
public function goodbyeAction() { echo 'Goodbye World'!; }
因为我们继承了 “Mage_Core_Controller_Front_Action”,我们可以使用一些父类已经定义好 的方法和变 量。比如父类会把 URL 后面跟的参数转换成 key/value 的数组。添 加如下代码到我们的执行控制器
public function paramsAction() { echo '<dl>'; foreach ($this->getRequest()->getParams() as $key=>$value) { echo '<dt><strong>Param: </strong>'.$key.'</dt>'; echo '<dt><strong>Value: </strong>'.$value.'</dt>'; } echo '</dl>'; }
请求如下 URL
http://www.magento1800.com/index.php/helloworld/index/params?aaa=11&bbb=22
你应该看到如下输出
Param: aaaValue: 11Param: bbbValue: 22
最后,让我们再写一个执行控制器,用来处理以下 URL
http://www.magento1800.com/index.php/helloworld/messages/goodbye
布局, 块和模板
一般的MVC架构是控制器controller传数据给视图view文件, 但是Magento里面是直接引用模型, 从模型取数据, 这样设计就导致了视图被拆分成块Block和模板Template. 块是PHP对象, 模版是原始PHP文件, 混合了HTML和PHP代码, 每一个块都和一个唯一模板文件绑定. 在模版文件PHTML中, $this就是指该模板文件对应的块对象.
嵌套块
Magento可以在块中嵌套块.
布局对象
创建和启用模型
创建模型有以下四个步骤:
1. 启用模型
2. 启用资源模型
3. 在资源模型中添加实体, 对于简单的模型来说, 实体就是数据表的名字
4. 为资源模型设置读,写适配器
假如这些已经设置好了, 那么如何使用呢, Magento中用以下方式来实例化一个模型
$model = Mage::getModel('helloworld/blogpost');
启用模型
修改模块的config.xml
<global> <!-- ... --> <models> <helloworld> <class>Zhlmmc_Helloworld_Model</class> <!-- need to create our own resource, can't just use core_mysql4 --> <resourceModel>helloworld_mysql4</resourceModel> </helloworld> </models> <!-- ... --> </global>
在模块文件夹里创建这个类
File: app/code/local/Test/Helloworld/Model/Blogpost.php
class zhlmmc_helloworld_Model_Blogpost exitends Mage_Core_Model_Abstract {
protected function _construct() {
$this->_init('helloworld/blogpost');
}
}
其中_construct不是PHP的构造函数__constract, 而是应该调用父类已经定义好的'_init'fangfa , 参数是资源模型URI.
启用资源模型并添加实体
下面我们要为模型设置资源模型. 资源模型才是真正和数据库对话的组建. 在模型配置中:
<resourceModel>helloworld_mysql4</resourceModel>
我们不需要显示的调用资源模型那个, 但是当一个模型需要访问数据库的时候, Magento会自动实例化一个资源模型来使用
Mage::getResourceModel('helloworld/blogpost')
这里的helloworld/blogpost就是我们给模型的_init传入的参数
需要在config.xml中添加资源模型的声明
<global>
<!-- ... -->
<models>
<!-- ... -->
<helloworld_mysql4>
<class>Zhlmmc_Helloworld_Model_Resource_Mysql4</class>
</helloworld_mysql4>
</models>
</global>
=======================================
Magento 1.8.0.0安装的几个坑, 安装了4次才搞定.
首先PHP.INI执行最大时间设置成3600, 因为创建数据库过程很慢.
其次为127.0.0.1设置viturehost, 指向一个自定义域名, 再把这个域名配置到自己的hosts里面, 因为Magento有些配置只认域名.
然后安装之前改下面2个地方
复制magento根目录下 /errors/local.xml.sample 并命名为/errors/local.xml
改变magento根目录下/lib/Zend/Cache/Backend/File.php
文件里面
protected $_options = array(
'cache_dir' => NULL,
'file_locking' => true,
为
protected $_options = array(
'cache_dir' => 'tmp/',
'file_locking' => true,
然后在根目录下创建tmp文件夹.