magento跟国内的开源框架有些许不一样,也有MVC架构的思想,但又并不完成一样是有所变化的,Magento它很多东西是由交由xml配置文件来主导,这样的好处是更灵活了,但对于开发人员来说,学习成本更高了!

对于magento后端开发人员来说,在理解目录结构后,再理清magento的模块概念也是很重要的一个事情,以下几点说明,希望能给到后端开发人员一些帮助:

一、Magento模块里面包含Model、Block、Controllers、Helper、sql、etc、目录,这几个目录有什么用?在实际开发中又是怎么使用呢?

Model:mvc框架下的M是一致的概念 ,读取数据库数据的,不太相同的地方是Model是获取一条数据,要获取多条数据,就得使用资源功能,目录对应是Model/Mysql4或Model/Resource(由etc/config.xml里面的resourceModel标签进行声明)

在magento系统中要获取一条数据,使用Model写法如下:
Mage::getModel('sales/order')->load($id);这将会调用app/code/core/Mage/Sales/Model/Order.php文件通过数据表字段唯一id拿到一条订单信息

而要获取多条数据时,是使用model资源功能写法如下:
Mage::getResourceModel('sales/order_collection')->addFieldToFilter('customer_id',1);这将会调用app/code/core/Mage/Sales/Model/Resource/Order/Collection.php文件,通过addFieldToFilter传入参数查询数据

Magento在model层也做了更高度的的封装处理,并不像于国内开源框架那样直接使用sql拼接进行查询,当然也是可以那样的操作,这是后话,并不在此做说明


Block:是块的概念 magento将前端V层,拆分成Layout(布局)\block(块)\template(模板)三大块了;
Layout\template位置在app/design/frontend/default/default下,layout是xml配置文件方式存在的,magento通过Layout布局文件配置了将block及template连接在一个,block负责数据,而template负责基础的html输出;

从View层面来说Block其实就是Model层,所有templete的数据都是从block获取,模板层使用$this->getData()就是调用了Block里面的方法。而在Block文件里面可以自定义方法返回数据或使用getModel方式来返回数据 (用mmvc来形容magento可能更合适,block/model都可做为m层,block是view的M层,而model是数据库读取操作的M层)


Controllers:控制器层 magento的C层也并不像国内开源系统那样,直接调model及view层模板,这部分工作交由layout(app/design/frontend/default/default/layout/***.xml)处理了,那样会更灵活
magento的控制器更多是一个url路由工作以及loadLayout()、renderLayout()进行view层的加载、引导、输出


Helper:帮助类 这个好像也没多少东西可以说的,跟其它框架的帮助类是一致的


sql:模块安装/升级目录 这是一个非常有意思的功能,在其它框架里面,如果要对数据库表进行结构调整或增加表时,可能是直接写一条sql放到mysql直接执行,而在magento最好的方式是交sql目录来处理,好处是能按模块版本进行数据库增/删/改调整,不需要其它电脑再执行sql,能避免数据表结构调整时总要手动去执行sql语句,

sql下文件命名是:
sql/模块名_setup/install-版本号.php
sql/模块名_setup/mysql4-upgrade-旧版本号-新版本号.php
而版本号对应着etc/config.xml文件里面的version标签,版本号自己自定义与sql下文件名版本号一致就行,这里面的文件,只会依据version号执行一次,完成升级后,就不会再执行,如果需要重新升级,可将core_resource表里面对应数据更新一下版本号,或删除,再刷新站点就可以!


etc:模块核心配置文件 这是magento模块最为重要的文件,也是非常折腾人的地方,xml格式的文件,里面可以定义数据表名、model、model资源、block、后台标签、权限配置……
etc/config.xml:包含modules、frontend、adminhtml、global……等标签

  • modules:用于定义模块名,版本号(可配合sql目录进行数据库增/删/改操作)
  • frontend:用于定义前台用到的功能,如:routers(路由)、layout(布局)、translate(翻译)、events(事件)标签
  • adminhtml:用于定义后台用到的功能,如:translate(翻译)、events(事件)标签
  • global:用于定义全局用到的功能,如:models(数据模块)、blocks(块)、helper(帮助类)、events(事件)标签

etc/adminhtml.xml: 可配置后台导航,如:menu标签、权限acl标签)

模块下的etc配置文件是magento模块的核心,所有model\control\block…都需要在这里面先声明了,才能生效,才能在其它地方使用


app/etc/modules:模块声明目录 所有magento的模块都要在这个地方放一个xml配置文件,主要是声明模块让magento能启用模块,内容如下:

<?xml version="1.0"?>
<config>
    <modules>
        <Sna_Sales>
            <!--active 这是开启关闭模块-->
            <active>true</active> 
            <codePool>local</codePool>
        </Sna_Sales>
    </modules>
</config>
app/etc/modules/Sna_sales.xml
二、magento的事件监听与计划任务

Model文件下,有一个Observer.php的文件,这是magento默认事件监听之用,产品修改/订单保存/用户登录/控制器加载等都会产生一个事件,magento可以通过对事件的监听插入一些其它的操作,在其它框架这也称为钩子,概念其实是一样的

而事件监听是通过etc/config.xml的events标签来声明调用。events是global\frontend\adminhtml三个标签的下级标签,对应为全局、前台、后台事件,更多信息自行查看etc/config.xml文件

三、magento获取数据特殊点

一、$order = Mage::getModel('sales/order')->load(12321);
二、$conn = Mage::getModel('sales/order')->getCollection()>addFieldToFilter('item_id', array('eq' => $itemsid));
三、$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$sql = "select * from sales_flat_order where entity_id = 12321";
$read->fetchAll($sql);

magento一般都是通过getModel->load来获取数据的,但以上几种写法,又有什么不同的地方呢?未深入了解过magento系统的开发者会很乱。

第一种:getModel->load方式: 是调用Model数据类型,主要是获取一条数据之用,load一般都是数字,是字段的唯一值。
Model数据类型涉及的代码位于:app/code/core/<包>/<模块》/Model
示例代码文件位置是:app/code/core/Mage/Sales/Model/Order.php

可以用$order->getData('grand_total')方式获取订单支付金额信息;
更为常用的方式是$order->getGrandTotal(),grand_total转为GrandTotal写法,前面增加get,第一个字符g及_后一个字符t,转为大写!变成getGrandTotal,这对于magento所有数据模型都是通用的,load数据后,要输出数据表的某字段值,按此方法就可以了!

这种方式,也会造成很多magento开发者的疑惑,为什么在app/code/core/Mage/Sales/Model/Order.php里面总找不到function get???()定义的方法,它不应该是在对象类里有一个类似的方法才对吗?因为magento的load数据后,会自行将表字段转为数据对象,也是很多时候我们能看到使用$order->get???()输出数据,但却总找不到function在哪里原因,因为这并不是一个自定义的方法,而是一个数据内容(注意:有一些get???()是会在model层进行功能重写,所以能找到function)。
而与之想对应的还有set???()方式来设置值,在load数据之后,$order->setMyinfo('这是我'),再使用$order->getMyinfo()就能输出。

magento的这个特点在所有拿数据的地方都是通用的,block、model、control、view层都经常会看到,只要明白了这一点(get方法一般是拿数据的,并不一定会有对应的function),就不会再有疑惑

第二种getModel(‘?/?’)->getCollection(): 是调用Resource资源数据类型,主要是用于获取多条数据之用,magento会将数据表与model进行深层次集成,使用资源类型就能获取某模块下某些表数据的多条记录,相对来说,会比较方便!magento的产品eva模型就把数据库拆分的很细,在获取产品信息时,使用Resource资源类型读取数据会比直接拼接sql读取数据库更为方便、直接。
资源功能涉及的代码位于:app/code/core/<包>/<模块》/Model/Resource

第三种$read = Mage::getSingleton('core/resource')->getConnection('core_read'): 这是为了方便直接读取数据库之用,与之相应的还为core_wirte的方式,为写入表数据之用,某一些功能或模块在不使用Resource资源时,就可以使用此方式来获取数据,如果你不想使用magento的resource资源功能,也可以使用此方式直接操作数据库

后记:

用magento1开发已经4年,从不熟悉到现在独立开发模块、拆分magento系统做独立接口去实现业务…此magento开发教程,将会从开发角度讲解一些开发细节的问题,这也算是对M1开发记录的一个小总结吧。
目前magento官方已经停止对1版本更新,但依然有很多公司还会用着M1版本(功能太多,平滑迁移还是要花时间)希望此文章能对m1开发者一些帮助。