Modules->模块

Controller->控制器

Model->模型

Magento是这个星球上最强大的购物车网店平台。当然,你应该已经对此毫无疑问了。不过,你可能还不知道,Magento同样是一个面向对象的PHP框架。你可以配合Magento购物车程序强大的功能,开发动态WEB应用程序。

这是Magento中文开发手册的开篇,我们会在整个手册中介绍绝大部分Magento的开发框架特性。不要想在这片文章中立刻掌握所有的特性。这仅仅是个开始,但是足够让你在同行中鹤立鸡群了。

在这片文章中,你将了解到:

  • Magento模块(Magento Modules)代码组织形式
  • 配置型MVC架构
  • Magento控制器(Magento Controllers)
  • 基于URI的模型实例化(Context-based URI Model Loading)
  • Magento模型(Magento Models)
  • Magento助手(Magento Helpers)
  • Magento布局(Magento Layouts)
  • 事件监听(Observers)
  • Magento类重写(Class Overrides)
  • 总结

开始之前,你可以试着看下Magento MVC模式的一个图形化直观体现。Magento_MVC.pdf

Magento模块中的代码组织形式

Magento通过将代码放入独立的模块进行组织。在一个典型的PHP MVC应用中,所有的控制器会被放在一个文件夹中,所有的模型会被放在另外一个文件夹里,等等。而在Magento中,文件是基于功能进行分组的,这种分组后的代码块叫做模块。

Magento的代码:

举例来说,如果你想寻找Magento中关于付款的功能,你仅仅需要找到下面代码中的文件夹,就能获取所有的控制器,模型,助手,Blocks等。

app/code/core/Mage/Checkout

如果你想寻找Magento中关于Google Checkout的功能,也仅仅需要找到如下文件夹,即可获取所有你想要的信息。

app/code/core/Mage/GoogleCheckout

你的代码:

如果你想扩展Magento,千万不要想当然的去修改core文件夹中的文件,也不要将你自己的控制器,模型,助手或者Blocks放在Core文件夹中。所有对于Magento的扩展,都将在local文件夹中进行。

app/code/local/<Package>/<Modulename>

Package(也可称为命名空间,当然这不是PHP手册中提到的命名空间)是唯一的命名,通过Package来标识你的公司,组织或个人。通过Package,世界范围内的Magento社区在创建模块扩展时,能够使用他们自己的Package名称,以避免与其他开发者有命名冲突。

创建一个新的模块时,你需要告诉Magento新模块的相关信息。可以通过添加一个XML文件在下面的目录中。

app/etc/modules

在这个目录中有两类xml文件,第一种用来开启独立的模块,以下列方式命名:

Packagename_Modulename.xml

第二种文件用来从一个Package中开启多个模块,以下列方式命名:

Packagename_All.xml

配置型MVC系统

Magento是一个配置型MVC(Configuration-based MVC)系统。另外一种MVC系统则是大部分PHP框架使用的,约定性MVC(convertion-based MVC)。

在约定型MVC系统中,如果你添加一个控制器,或者一个模型,只需要根据约定的内容,创建这个文件以及类即可,系统会自动识别它。

而在配置型MVC系统中,比如Magento,除了需要添加相应的文件及类之外,还需要明确的告诉系统该类的存在。在Magento中,每个模块都有一个config.xml文件。这个文件中包含了一个模块相关的配置信息。在运行时,所有模块的配置文件,都会被加载到一个巨大的配置文件树中(后面的文章会介绍如何查看这个配置树)。

比如,想在模块中使用模型。你需要添加类似下面的代码,来告诉Magento你会在这个模块中使用这个模型。

<models>

<packagename>

<class>Packagename_Modulename_Model</class>

</packagename>

<models>

当然,这种配置不仅限于模型,对于控制器,助手,Blocks,路由,事件句柄等都需要在该模块的config.xml中进行相关的配置。

Magento控制器(Magento Controllers)

在任何PHP系统当中,核心文件肯定是PHP文件。Magento也不例外,index.php是Magento的核心文件。

不过,永远不要编辑index.php中的任何代码。在MVC系统中,index.php的左右大概有以下几项:

  • 检测URL地址。
  • 根据路由规则,将访问的URL地址分发到控制器类中的方法。
  • 初始化控制器,并调用相应的动作方法。这一步骤叫做分发。Dispatching。

这意味着Magento(或任何MVC系统)每一个有效的entry point都是控制器文件中的一个方法。一起来看下面这个URL:

http://example.com/catalog/category/view/id/25

上述域名后URL地址可以被分拆为以下几个部分。

Front Name – catalog

该URL的第一部分被称为Front Name。它用来指示Magento应该在哪个模块中寻找URL中的控制器。在这个例子中,catalog就是Front Name,对应于catalog模块。

Controller Name – Category

第二部分指示Magento应该匹配的控制器。每个拥有控制器的模块都包含一个‘controllers’的文件夹,用来存放该模块下的所有控制器。上述URL地址,匹配了下面这个控制器文件。

app/code/core/Mage/Catalog/controllers/CategoryController.php

其中的类定义格式大概为:

class Mage_Catalog_CategoryControllerextends Mage_Core_Controller_Front_Action

{

}

在Magento中,所有的控制器都继承自Mage_Core_controller_Front_Action类。

Action Name – view

第三部分是一个action方法的名称。在此URL中,view便是一个action方法的名字。

class Mage_Catalog_CategoryControllerextends Mage_Core_Controller_Front_Action {

public function viewAction() {

}

}

Paramater/Value – id/25

任何位于action方法名之后的路径,都会被认为是key/value形式传递的GET变量。那么在我们的例子当中,’id/25′表示有一个值为25的$_GET['id']变量。

如前所述,如果你想让自定义模块使用控制器,你必须对它进行配置。下面是在模块中开启控制器的代码。

<frontend>

<routers>

<catalog>

<use>standard</use>

<args>

<module>Mage_Catalog</module>

<frontName>catalog</frontName>

</args>

</catalog>

</routers>

</frontend>

现在不清楚上述内容都是什么意思还没关系,但是注意<frontName>catalog</frontName>。这是用来关联模块与URL地址中frontname的。Magento核心代码选择将一个模块的名字与frontname一致,但这不是强制规定的。

Multiple Routers

上面提到的路由规则主要是针对Magento购物车程序(即你所能看到的前端)。如果Magento在URL中无法匹配到正确的控制器/动作,它会尝试使用针对Admin程序(后台管理端)的另一套路由规则。如果依旧无法正确匹配,它会使用一个特殊的控制器Mage_Cms_IndexController。

CMS控制器会检查Magento内容管理系统中是否有内容需要输出,如果有内容输出,则读取该内容,如果找不到,则输出404页面。

例如,Magento默认的首页就是在使用CMS控制器。

Context-Based URI 模型读取

目前为止,我们已经建立了一个控制器以及一个方法,到实例化一个类做点什么的时候了。Magento提供了一种特殊的方式去实例化模型,助手以及Blocks,即使用Mage全局类提供的静态工厂方法。例如,

Mage::getModel('catalog/product');

Mage::helper('catalog/product');

‘catalog/product’字符串被称为Grouped Class Name。通常叫做URI。Grouped Class Name的第一部分用来指示该类存在于哪个模块当中。第二部分用来决定哪个类将被调用。

那么,上述例子中,‘catalog’对应于app/code/core/Mage/Catalog模块,也就意味着我们的类名将以Mage_Catalog开头,然后根据调用的类型,将product类名加入到最后一部分。即,

Mage::getModel('catalog/product');

Mage_Catalog_Model_Product;

Mage::helper('catalog/product');

Mage_Catalog_Helper_Product;

Magento 模型

和现在的多数框架一样,Magento也提供ORM支持。ORM让你能够专注于数据,而非无尽的SQL语句。例如,

$model = Mage::getModel('catalog/product')->load(27);

$price =$model->getPrice();

$price += 5;

$model->setPrice($price)->setSku('SK1231414');

$model->save();

在上面这个例子中,我们调用了“getPrice”和“setPrice”方法。然而,在Mage_Catalog_Model_Product类中并没有此方法。那为什么上面这个例子能够使用这些方法呢?因为Magento的ORM系统中使用了PHP的_get和_set魔术方法。

调用$product->getPrice()会获取模型属性price,而调用$product->setPrice()会设置price属性。当然,所有的这些都假设模型类没有getPrice和setPrice方法。如果它们存在于模型类中,PHP魔术方法会被忽略。如果你有兴趣知道这是如何实现的,可以参考Varien_Object类,所有的模型类都继承自该类。

如果你想获取模型当中所有的数据,可以直接调用$product->getData()方法,它会返回包含所有字段的一个数组。

你可能已经注意到上例中的方法存在使用->符号链接的形式:

$model->setPrice($price)->setSku(‘SK12312542′);

能够使用这种方式调用方法,最主要的原因是所有的set方法都会返回一个模型的实例。你会经常在Magento的核心代码中看到此类调用方法的形式。

Magento的ORM系统中还包含一种通过Collections接口查询多个对象的方式。下例会读取系统中所有5美元的产品。

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

->getCollection()

->addAttributeToSelect('*')

->addFieldToFilter('price','5.00');

这里我们又一次看到了链接调用方法的形式。Collections use the PHP Standard Library to implement Objects that have array like properties.(这句超出理解范围)。

foreach($products_collection as $product)

{

echo $product->getName();

}

在上面的一个例子当中,你可能注意到了addAttributeToSelect方法。这里单独提到此方法,是因为它代表了Magento模型中的一个类别。Magento拥有两种形式的模型对象。一种是传统的“一个对象,一张表”的Active Record模型。当你实例化这些模型的时候,所有的属性都会被自动选取。

Magento中第二种模型叫做Entity Attribute Value(EAV)模型。这种模型会按照一定的规律将数据分散存储在数据库不同的表中。EAV模型的高级特性,让Magento不用在增加一种产品属性的时候改变数据库模型(一般的购物车系统在增加新的属性时,有两种方式,一种是增加数据库字段,一种是使用预留的空字段。),从而保证了Magento系统的高度扩展性。当创建一个EAV模型的collection时,Magento会conservative in它会查询的字段数,所有你可以使用addAttributeToSelect来制定你想获取的列,或者使用addAttributeToSelect(*)来获取所有列。

Magento Helpers 助手

Magento的助手类包含一系列实用的方法,通过这些方法可以对对象及变量做日常性的操作。例如,

$helper = Mage::helper('catalog');

是否注意到这里舍弃了Grouped Class Name的第二部分?每个模块都有一个默认的data助手类。下面的语句与上面的作用是相同的,即默认使用模块下的data助手类。

$helper = Mage::helper('catalog/data');

大部分的助手类继承自Mage_Core_Helper_Abstract,默认提供了很多使用的方法。

$translated_output =$helper->__('Magento is Great');

if ($helper->isModuleOutputEnabled()) {

}

Magento Layout 布局

目前为止,我们已经介绍了控制器,模型以及助手。在典型的PHP MVC系统当中,在操作模型之后,一般会

  • 传递变量到视图中。
  • 系统会自动读取默认的外层布局
  • 接着将视图读取到外层布局中

不过,如果你仔细观察Magento 控制器动作方法,你不会看到这些步骤,

public function galleryAction() {

if (!$this->_initProduct()) {

if (isset($_GET['store']) && !$this->getResponse()->isRedirect()) {

$this->redirect('');

}elseif (!$this->getResponse()->isRedirect()) {

$this->_forward('noRoute');

}

return;

}

$this->loadLayout();

$this->renderLayout();

}

不同于典型PHP MVC形式的是,控制器动作方法,以两个输出布局的方法结束。所以说,Magento MVC系统中的V视图部分可能与你经常使用的大相径庭。因为,你必须在控制器中明确的输出布局。

并且,Magento的布局本身也区别与你经常使用的MVC系统。Magento布局是一个包含嵌套或者树状的Block对象的对象。每一个Block对象输出一部分HTML,输出HTML的环节包含两个部分,PHP代码组成的Block以及.phtml模板文件。

Blocks对象负责与Magento系统交互并从模型中获取数据,而phtml模板文件则为页面生成必须的HTML代码。

例如,页面头部Block文件app/code/core/Mage/Page/Block/Html/Head.php使用与其对应的page/html/head.phtml模板文件。

换种方式说的话,Blocks类就像迷你控制器,而.phtml文件就是视图文件。

默认的,当你调用,

1

2

$this->loadLayout();

$this->renderLayout();

Magento will load up a Layout with a skeleton site structure(此段能够理解,但想不到最佳翻译,大概意思是Magento会读取网站的布局框架)。这些结构Blocks用来输出head,body以及设定单栏或多栏的布局。另外,还有一些内容Blocks负责实际输出像导航,产品分类等。

“结构”和“内容”Blocks在布局系统中是随意设置的。一般不会在代码中刻意添加代码,从而区分一个Block是结构还是内容,但是Blocks要么属于“结构”,要么属于“内容”。

为了添加一个内容Blocks到布局中,你需要告诉Magento系统

“Magento,快把这几个Blocks添加到内容Block 里”

或者

“Magento,把这边几个Blocks放到“左边栏”结构Block里”

这些可以通过控制器中的代码进行控制,

public function indexAction() {

$block =$this->getLayout()->createBlock('adminhtml/system_account_edit');

$this->getLayout()->getBlock('content')->append($block);

}

但是更常用的方式(至少在前台购物车应用中)是使用基于XML文件的布局系统。

在一款风格中,基于XML文件的布局 允许你删除正常输出的Blocks或者添加默认的skeleton区域(即Structure Blocks)。例如下面这个XML布局文件,

<catalog_category_default>

<reference name="left">

<block type="catalog/navigation" name="catalog.leftnav" after="currency" template="catalog/navigation/left.phtml" />

</reference>

</catalog_category_default>

上面这段代码的作用是,在catalog模块的category控制器的默认动作方法中,将catalog/navigation Block插入到左边栏结构Block中,并使用catalog/navigation/left.phtml模板文件。

关于Blocks还有一个比较重要的特性。在模板文件中,你会看到很多类似下面的代码,

1

$this->getChildHtml('order_items')

这是Block输出套嵌Block的方式。但是,只有在XML布局文件中明确声明一个Block包含另一个子Block时,才能在模板文件中通过getChildHtml()方法调用子Block的模板文件。

例如,在XML布局文件中,

<catalog_category_default>

<reference name="left">

<block type="catalog/navigation" name="catalog.leftnav" after="currency" template="catalog/navigation/left.phtml">

<block type="core/template" name="foobar" template="foo/baz/bar.phtml" />

</block>

</reference>

</catalog_category_default>

那么从catalog/navigation Block中,我们才可以调用$this->getChildHtml(‘foobar’);

Observers 观察者

和许多优秀的面向对象系统一样,Magento通过实现观察者模式给用户作为钩子。对于在页面请求时(模型存储,用户登录等)调用的特定动作方法,Magento会生成一个事件信号。

当创建新的模块时,你可以“监听”这些事件。比如说,你想在特定用户登录商店的时候发一封邮件到管理员信箱里,可以通过“监听”customer_login事件做到。

<events>

<customer_login>

<observers>

<unique_name>

<type>singleton</type>

<class>mymodule/observer</class>

<method>iSpyWithMyLittleEye</method>

</unique_name>

</observers>

</customer_login>

</events>

接下来是当用户登录时应该运行的代码:

class Packagename_Mymodule_Model_Observer

{

public function iSpyWithMyLittleEye($observer)

{

$data =$observer->getData();

//code to check observer data for out user,

//and take some action goes here

}

}

Class Overrides 类的复写

最后,Magento系统还提供了类的复写功能,你可以通过自己的代码覆盖核心代码里的模型,助手,和Blocks类。

下面举些例子帮助你更容易理解这个功能。产品的模型类是Mage_Catalog_Model_Product.无论何时,下面的代码被调用时,就会生成一个Mage_Catalog_Model_Product对象。

1

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

这是工厂模式。Magento的类复写系统运作模式大概是这样,

“Magento! 如果有请求对应catalog/product,不要实例化Mage_Catalog_Model_Product,让Packagename_Modulename_Model_Foobazproduct接手”

在模型中,类的覆盖方式及命名规则如下,

class Packagename_Modulename_Model_Foobazproductextends Mage_Catalog_Model_Product

{

}

通过这种方式,你可以改变父类中方法的行为,并且完全继承父类的所有功能。

class Packagename_Modulename_Model_Foobazproductextends Mage_Catalog_Model_Product

{

public function validate() {

//添加一些自定义的验证功能

return $this;

}

和之前所说的一样,复写同样需要在config.xml配置文件中进行配置。

<models>

<!-- tells the system this module has models -->

<modulename>

<class>Packagename_Modulename_Model</class>

</modulename>

<!-- does the override for catalog/product-->

<catalog>

<rewrite>

<product>Packagename_Modulename_Model_Foobazproduct</product>

</rewrite>

</catalog>

</models>

转载于:https://www.cnblogs.com/zhengyanbin2016/p/5688616.html

Magento 使用心得相关推荐

  1. Magento 1.9.X 系列教程

    Magento安装下载教学: Magento教程 1:免费购物车系统,轻松建立Magento第一步! Magento教程 2:Magento 社群版安装教学! Magento教程 3:如何在Magen ...

  2. magento系统自带批量小结

    2019独角兽企业重金招聘Python工程师标准>>> 接触magento也快2个月了,由什么都不知道的小白----------到能够独立搭建网站---------到独立写一点属性的 ...

  3. Java EE学习心得

    –Java EE学习心得   1.    称为编程专家的秘诀是: 思考-----编程--------思考------编程--.. 编程不能一步到位,不能一上来就编,必须先思考如何写,怎样写?然后再编程 ...

  4. 测试心得:微图书销售小程序

    测试心得:微图书销售小程序 前言 这个学期差不多也将近结束,经过大半个学期,从项目需求的确认和项目文档的编写,到一步步的设计与实现,现在终于到了测试阶段,但是我们在测试阶段也暴露出了很多bug,但是每 ...

  5. java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得

    该文章出自:http://www.cnblogs.com/hucn/p/3572384.html 分析工具:http://www.blogjava.net/jjshcc/archive/2014/03 ...

  6. magento常用软件

    常见问题:     1. 装完插件导致后台配置出现 Access denied 信息,需要重置账号权限,方可恢复正常.     2. 大多数无法安装插件时,请删除 /downloader/pearli ...

  7. 计算机财务应用实验心得,计算机会计实习心得-20210628124643.doc-原创力文档

    计算机会计实习心得 计算机会计实习心得1 毕业实践环节是大学生在完成全部课程后.走向社会之前最真实的一个模拟实验,对于我们财会专业的学生,平时注意注重理论学习,缺乏实践锻炼,因此实习显得尤为重要.在本 ...

  8. html5考试总结300字,期中考心得300字5

    为了检验学生半个学期所学的知识而进行的一次考试,有利于学生比较正式地检验自己平时的学习水平,根据这个成绩,学生可以及时的调整学习心态和方法,更有效率地进行下一阶段的学习,期中考试主要考察学生前半学期的 ...

  9. Assembly学习心得

    http://blog.csdn.net/etmonitor/ Assembly学习心得 说明: 最近开始准备把学到的.NET知识重新整理一遍,眼过千遍不如手过一遍,所以我准备记下我的学习心得,已备参 ...

  10. 什么叫安装文件索引服务器,搜出精彩 玩转Windows 2008系统心得

    [IT168 专稿]不少朋友已经在不经意间与Windows Server 2008系统进行了亲密接触,在一段时间的接触之后,不知大家对该系统的文件搜索功能会有什么样的体会?其实,Windows Ser ...

最新文章

  1. qq无限时间撤回消息bug_手机QQ新功能汇总,比微信有意思多了
  2. Redis重新连接弹性
  3. CTFshow 命令执行 web64
  4. 交换机网络嗅探方法之用ARP欺骗辅助嗅探
  5. TCP socket和web socket的区别
  6. 高安全性同态加密算法_坏的同态性教程
  7. scatter函数_散点图、箱线图、核密度函数……数据分析必备的9种可视化图表
  8. loadrunner / socket level data and wininet level data
  9. mysql 命令 示例,mysql语句大全
  10. 米斯特白帽培训讲义 漏洞篇 XSS
  11. [UWP]创建一个ProgressControl
  12. mysqlbinlog配置
  13. 我的世界服务器皮肤怎么用文件夹,我的世界怎么用皮肤文件,怎么通过文件夹更改皮肤...
  14. ORM的个人简单理解以及持久化和持久层的简单理解、Hibernate的简单理解,mybatis 的好处通俗易懂
  15. qq浏览器 广告拦截插件abp_【浏览器插件推荐】如何让QQ浏览器变得更加的高效...
  16. java实训心得体会3篇_java实训心得体会3篇
  17. 英语一窍不通能学计算机吗,英语一窍不通能学好软件么
  18. Maven打包失败:程序包XXX不存在
  19. 存款利息的计算,有1000元,想存五年,可按照五种办法存:
  20. decltype和拖尾返回类型

热门文章

  1. 【C/C++】C++函数
  2. oracle避免索引失效,Oracle优化你的查询--关于避免索引隐式失效
  3. 文件图片随机划分训练集和验证集
  4. Python之web服务利器Flask生产环境部署实践【基于gunicorn部署生产环境】
  5. java桥牌发牌算法
  6. Python下opencv(图像的阈值处理)
  7. 最大团问题和最大独立子集
  8. DevOps使用教程 华为云(9)代码检查
  9. kubernetes视频教程笔记 (36)-部署 prometheus granfana
  10. Docker教程小白实操入门(15)--如何使用WORKDIR、ENV、ARG和EXPOSE设置镜像